- 6. const、let与var的区别?
- 7. 箭头函数和普通函数的区别?
- 事件传播的三个阶段是什么??
- 1. 严格模式
- 作用域和闭包
- 执行机制
- JS
- 1. js有哪些数据类型?
- 2
. typeof 和 instanceof 区别是什么?简单实现一下 instanceof。 - 3. 其中typeof null是什么, 为什么?
- 4. [‘1’, ‘2’, ‘3’].map(parseInt)运行结果?
- 2.JavaScript对象的底层数据结构是什么?
- 5.基本类型对应的内置对象,以及他们之间的装箱拆箱操作?
- 6.理解值类型和引用类型?
- 7.null和undefined的区别?
- 8.至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型?
- 9.可能发生隐式类型转换的场景以及转换原则,应如何避免或巧妙应用
- 12.代码的输出结果?
- 14.函数的执行结果?
- 15.下面这些值哪些是假值?
- 16.
!!null; !!""; !!1;
下面代码的输出是什么? - 4.”attribute” 和 “property” 的区别是什么?
- 5.Promise.all 是干什么的?
- 6. 跨域的问题如何解决,什么是同源策略?
- 7. 如何实现服务器如何主动向浏览器发送数据?试写出三种实现方式并简要阐述。
- 8.下面代码的输出是什么?
- 9.什么是event loop?
- 1.理解ECMAScript和JavaScript的关系?
- 2.熟练运用es5、es6提供的语法规范
- 3.熟练掌握JavaScript提供的全局对象(例如Date、Math)、全局函数(例如decodeURI、isNaN)、全局属性(例如Infinity、undefined)
- 4.熟练应用map、reduce、filter 等高阶函数解决问题
- 5.setInterval需要注意的点,使用settimeout实现setInterval
- 6.JavaScript提供的正则表达式API、可以使用正则表达式(邮箱校验、去重等)解决常见问题?
- 7.JavaScript异常处理的方式,统一的异常处理方案?
- 8.下面代码的输出是什么?
- 9.下面代码的输出是什么?
- 10.下面代码的输出是什么?
- 9.下面代码的输出是什么?
- 11.下面代码的输出是什么?
- 12.下面代码的输出是什么?
- 13.下面代码的输出是什么?
- 14.下面代码的输出是什么?
- 15.下面代码的输出是什么?
- ES6
6. const、let与var的区别?
- 块级作用域
- 不具备在预编译时提升的特性
- 暂时性死区
- 变量不允许重复声明
其中,const在声明变量时必须初始化
ES6规定,
_let/const_
命令会使区块形成封闭的作用域。若在声明之前使用变量,就会报错。 总之,在代码块内,使用_let_
命令声明变量之前,该变量都是不可用的。 这在语法上,称为 “暂时性死区”( temporal dead zone,简称 TDZ)。
7. 箭头函数和普通函数的区别?
- (写法不同)省略了function函数声明关键字, 返回值return关键字可省
- 不会创建自己的this,函数内的this指向上级
- 是匿名函数,不能被当作构造函数, 不能使用new
- 不绑定arguments,取而代之用rest参数…解决
- 没有原型属性
- 不能用作 Generator 函数,不可以使用yield命令
**arguments**
是一个对应于传递给函数的参数的类数组对象。
事件传播的三个阶段是什么??
A: 目标 > 捕获 > 冒泡
B: 冒泡 > 目标 > 捕获
C: 目标 > 冒泡 > 捕获
D: 捕获 > 目标 > 冒泡
答案:D 原因:在捕获阶段,事件通过父元素向下传递到目标元素。 然后它到达目标元素,冒泡开始。
1. 严格模式
“use strict”启动。
目的:
- 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
- 消除代码运行的一些不安全之处,保证代码运行的安全;
- 提高编译器效率,增加运行速度;
- 为未来新版本的Javascript做好铺垫。
使用:1. 脚本首行(建议脚本放在立即执行的匿名函数) 2. 函数内部首行
限制(严格模式改变语法及运行是时的行为):
- 全局变量必须显式声明。(通常缺少声明的变量赋值默认为全局变量)
- 静态绑定。禁止使用with语句。创设eval作用域。
- 增强的安全措施。禁止this关键字指向全局对象(必须通过new 产生局部this)。禁止子在函数内部遍历调用栈(fn.caller\arguments)。
- 禁止删除变量(只有configurable设置为true的对象属性)。
- 显示报错。(对象的只读属性被被赋值/getter方法读取的属性被赋值/禁止扩展的对象添加新属性/删除不可删除的属性)
作用域和闭包
1.理解词法作用域和动态作用域
2.理解JavaScript的作用域和作用域链
3.理解JavaScript的执行上下文栈,可以应用堆栈信息快速定位问题
4.this的原理以及几种不同使用场景的取值
5.闭包的实现原理和作用,可以列举几个开发中闭包的实际应用
6.理解堆栈溢出和内存泄漏的原理,如何防止
7.如何处理循环的异步操作
8.理解模块化解决的实际问题,可列举几个模块化方案并理解其中原理
执行机制
1.为何try里面放return,finally还会执行,理解其内部机制
2.JavaScript如何实现异步编程,可以详细描述EventLoop机制
4.可以快速分析一个复杂的异步嵌套逻辑,并掌握分析方法
5.使用Promise实现串行
6.Node与浏览器EventLoop的差异
7.如何在保证页面运行流畅的情况下处理海量数据
JS
1. js有哪些数据类型?
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
注:Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。
2. typeof 和 instanceof 区别是什么?简单实现一下 instanceof。
typeof 适用于基础数据类型判断(不包含null),返回值为该类型的字符串。
返回值(七种):number, string, boolean, undefined, function, object, symbol 。
instanceof 一般用于判断引用类型,返回值为布尔值 (A instanceof B, A 是否在B的原型链上)
3. 其中typeof null是什么, 为什么?
结果: “object”
js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息。
- 000:对象
- 010:浮点数
- 100:字符串
- 110:布尔
- 1:整数
但是, 对于 undefined和 null 来说,这两个值的信息存储是有点特殊的。
null:所有机器码均为0
undefined :用 −2^30 整数来表示
4. [‘1’, ‘2’, ‘3’].map(parseInt)运行结果?
结果:[1, NaN, NaN]
parseInt(string,[ radix])
radix 可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。
如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x”或 “0X”开头,将以 16 为基数。
如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN。
返回值。如果被解析参数的第一个字符无法被转化成数值类型,则返回 NaN。
arr.map(function callback( currentValue[, index[, array]]) {
// return element for new_array
}[, thisArg])
callback生成新数组元素的函数,使用三个参数:
currentValue。callback 数组中正在处理的当前元素。
index可选。callback 数组中正在处理的当前元素的索引。
array可选。map 方法调用的数组。
thisArg可选。执行 callback 函数时值被用作this。
2.JavaScript对象的底层数据结构是什么?
在Pthyon里面叫做字典,在Ruby/Perl里面叫散列表。
5.基本类型对应的内置对象,以及他们之间的装箱拆箱操作?
String()、Number()、Boolean()、RegExp()、Date()、Error()、Array()、Function()、Object()、symbol()
装箱:把基本数据类型转化为对应的引用数据类型的操作(每当读取一个基本类型的时候,后台就会创建一个对应的基本包装类型对象,从而让我们能够调用一些方法来操作这些数据。)机制如下:
(1)创建String类型的一个实例;(2)在实例上调用指定的方法;(3)销毁这个实例;
拆箱:将引用类型对象转换为对应的值类型对象
它是通过引用类型的valueOf()或者toString()方法来实现的。如果是自定义的对象,你也可以自定义它的valueOf()/tostring()方法,实现对这个对象的拆箱。
6.理解值类型和引用类型?
值类型占用空间固定,保存在栈里面,操作的是值本身;引用类型占用空间不固定,保存在堆中,操作的是指向对象的一个指针。
注2:栈一般存放变量的值,内存空间由系统自动分配和释放;堆一般存放复杂对象,内存空间为动态分配,不主动释放的话,可能会由垃圾回收机制自动回收。
数据在内存中的存储结构,也就是物理结构,分为两种:顺序存储结构和链式存储结构。
- 顺序存储结构:是把数据元素存放在地址连续的存储单元里,其数据间的逻辑关系和物理关系是一致的。数组就是顺序存储结构的典型代表。
- 链式存储结构:是把数据元素存放在内存中的任意存储单元里,也就是可以把数据存放在内存的各个位置。这些数据在内存中的地址可以是连续的,也可以是不连续的。链表就是顺序存储结构的典型代表。
和顺序存储结构不同的是,链式存储结构的数据元素之间是通过指针来连接的,我们可以通使用指针来找到某个数据元素的位置,然后对这个数据元素进行一些操作。
7.null和undefined的区别?
undefined和null在if语句中,都会被自动转为false,相等运算符甚至直接报告两者相等。
null表示”没有对象”,即该处不应该有值。典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义。典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
注: 最初区分:null是一个表示”无”的对象,转为数值时为0;undefined是一个表示”无”的原始值,转为数值时为NaN。
8.至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型?
- typeof,返回基础数据类型(除null,NaN), 无法区分引用类型(均为”object”)
typeof null // “object” typeof NaN // “number”
instanceof,只能用来判断复杂数据类型,因为instanceof 是用于检测构造函数(右边)的 prototype 属性是否出现在某个实例对象(左边)的原型链上。
- constructor(构造函数的构造器)
constructor 作用和 instanceof 非常相似。但 constructor 检测 Object 与 instanceof 不一样,还可以处理基本数据类型的检测。
(1)null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。
(2)函数的 constructor 不稳定,主要是类的原型进行重写,在重写的过程中有可能把之前的constructor给覆盖了,这样检测出来的结果就是不准确的
- Object.toString.call(obj), 返回”[object, 类型]”,注意返回的格式及大小写,前面是小写,后面是首字母大写。
对于 Number,String,Boolean,Array,RegExp,Date,Function 原型上的 toString 方法都是把当前的数据类型转换为字符串的类型
注:Array.isArray(object)用于判断一个对象是否为数组
9.可能发生隐式类型转换的场景以及转换原则,应如何避免或巧妙应用
- 转换为boolean类型, !操作符,> < == 操作符 (==才会进行类型隐式转换,===先比较类型是否相同,不同则直接返回false)
2. 转换为number类型 ,+ - * / % 操作符, ++ 操作符
3. 转换为string类型, + 操作符 (只要两边有一个为字符串,则+为字符串连接符。当为null,boolean或者undefined时编译器先调用Number()将其转换成数值类型。)12 + “34” 或 “12” + 34 均为 “1234”
符:强制类型转换Number、Boolean、parseInt、parseFloat、String
常见类型转换
2string,toString、join、JSON.stringify
2array, split、Array.prototype.of、Array.prototype.from
12.代码的输出结果?
let a = 3;
let b = new Number(3);
let c = 3;
console.log(a == b);
console.log(a === b);
console.log(b === c);
输出: true false false
解释:==会引发隐式类型转换,右侧的对象类型会自动拆箱为Number类型。new Number()是一个内置的函数构造函数,是对象类型。
14.函数的执行结果?
function sum(a, b) { return a + b; } sum(1, “2”);
输出:”12” 原因: 隐式类型转换
15.下面这些值哪些是假值?
0; new Number(0); (“”); (“ “); new Boolean(false); undefined;
JavaScript中只有6个假值: undefined、null、NaN、0、’’ (empty string)、false
函数构造函数,如new Number和new Boolean都是真值。
16. !!null; !!""; !!1;
下面代码的输出是什么?
4.”attribute” 和 “property” 的区别是什么?
Attribute(特性)
- attribute特性由HTML定义,所有出现在HTML标签内的描述节点都是attribute特性。
- attribute特性的类型总是字符串类型。拿上边的DIV为例,
document.getElementById('test').getAttribute('custom-attr')
或者$('#test').attr('custom-attr')
总是返回字符串类型
Property(属性)
- property属性属于DOM对象,DOM实质就是javascript中的对象。我们可以跟在js中操作普通对象一样获取、设置DOM对象的属性,并且property属性可以是任意类型。
- 非自定义的attribute特性与property有1:1的映射关系,比如:id,class,title等。
- 非自定义的property(attribute)改变的时候,其对应的attribute(property)在多数情况下也会改变。
- 当对应的property改变的时候,attribute特性value的值一直未默认值,并不会随之改变。
(最佳实践)在javascript中我们推荐使用property属性因为这个属性相对attribute更快,更简便。尤其是有些类型本该是布尔类型的attribute特性。比如:”checked”, “disabled”, “selected”。浏览器会自动将这些值转变成布尔值传给property属性。
5.Promise.all 是干什么的?
用于执行其参数中的所有promise,当其参数中的所有promise均为resolve时,promise.all返回的promise为resolve,当参数promise中存在reject时,其reject为参数promise中第一个reject的值。
6. 跨域的问题如何解决,什么是同源策略?
答案:同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源,同源是指协议相同域名相同端口相同,解决方案:JSONP,WebSocket,CORS。
7. 如何实现服务器如何主动向浏览器发送数据?试写出三种实现方式并简要阐述。
答案: 轮询,Websocket, 服务器发送事件(Server-sent events)
8.下面代码的输出是什么?
(() => {
let x, y;
try {
throw new Error();
} catch (x) {
(x = 1), (y = 2);
console.log(x);
}
console.log(x);
console.log(y);
})();
A:
1
undefined
2
B:undefined
undefined
undefined
C:1
1
2
D:1
undefined
undefined
答案: A 原因: catch接收的变量x
是属于catch
作用域的。9.什么是event loop?
答案:javascript的事件循环,由于 JS 是单线程的,同步执行任务会造成浏览器的阻塞,所以我们将 JS 分成一个又一个的任务,通过不停的循环来执行事件队列中的任务。这就使得当我们挂起某一个任务的时候可以去做一些其他的事情,而不需要等待这个任务执行完毕。
关键步骤如下:执行最旧的task(一次)
- 检查是否存在microtask,然后不停执行,直到清空队列(多次)
- 执行render
task主要包含:**setTimeout**
、**setInterval**
、**setImmediate**
、**I/O**
、**UI交互事件**
microtask主要包含:**Promise**
、**process.nextTick**
、**MutaionObserver**
整个最基本的Event Loop如图所示:
- queue可以看做一种数据结构,用以存储需要执行的函数
- timer类型的API(setTimeout/setInterval)注册的函数,等到期后进入task队列(这里不详细展开timer的运行机制)
- 其余API注册函数直接进入自身对应的task/microtask队列
- Event Loop执行一次,从task队列中拉出一个task执行
- Event Loop继续检查microtask队列是否为空,依次执行直至清空队列
执行优先级:
说回正经的,如果从规范来看,microtask优先于task执行。那如果有需要优先执行的逻辑,放入microtask队列会比task更早的被执行,这个特性可以被用于在框架中设计任务调度机制。
如果从node
的实现来看,如果时机合适,microtask的执行甚至可以阻塞I/O,是一把双刃剑。
综上,高优先级的代码可以用Promise
/process.nextTick
注册执行。
执行效率:
从node
的实现来看,setTimeout
这种timer类型的API,需要创建定时器对象和迭代等操作,任务的处理需要操作小根堆,时间复杂度为O(log(n))。而相对的,process.nextTick
和setImmediate
时间复杂度为O(1),效率更高。
如果对执行效率有要求,优先使用process.nextTick
和setImmediate
。
1.理解ECMAScript和JavaScript的关系?
javascript实现包含三个方面:
1. ECMAscript(根据MCMA-262标准,实现的通用脚本语言规范)
2. DOM— js需要支持对DOM的维护,通过document,element对象实现.这些都是在ES中没有的.
3. BOM— js需要支持对BOM的维护,通过window对象实现.这些都是在ES中没有的.
2.熟练运用es5、es6提供的语法规范
3.熟练掌握JavaScript提供的全局对象(例如Date、Math)、全局函数(例如decodeURI、isNaN)、全局属性(例如Infinity、undefined)
4.熟练应用map、reduce、filter 等高阶函数解决问题
5.setInterval需要注意的点,使用settimeout实现setInterval
setTimeout中两个参数分别是回调函数和时间(毫秒)。
1、回调函数不能传递带参数的函数
2、setInterval 周期性的调用函数或计算方法,关闭用clearInterval 。setInterval 和clearInterval 是一对一的关系。比如想要对同一个按钮在不同场景中,使用周期性的调用不同的函数,那么需要先关掉上一个setInterval,再设定另一个setInterval
function newSetInterval (callbackFunction, millisecond) {
function inner() {
callbackFunction()
setTimeout(inner, millisecond)
}
inner()
}
6.JavaScript提供的正则表达式API、可以使用正则表达式(邮箱校验、去重等)解决常见问题?
/^\w+@[a-z0-9]\.[a-z]+$/.test()
str.replace(/(.)(\1)+/g,'$2') //相邻元素去重
// 排序 -> 去重
var sortedStr = str.split("").sort().join("")
sortedStr.replace(/(.)(\1)+/g,'$2')
7.JavaScript异常处理的方式,统一的异常处理方案?
1、try..catch 2、 window.onerror 两种方式捕获异常
throw new Error 抛出异常
8.下面代码的输出是什么?
const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);
输出: [1, 2, 3, empty × 7, 11] 解释:当你为数组中的元素设置一个超过数组长度的值时,JavaScript
会创建一个名为“空插槽”的东西。 这些位置的值实际上是undefined
9.下面代码的输出是什么?
function getAge(...args) {
console.log(typeof args);
}
getAge(21);
A: "number"
B: "array"
C: "object"
D: "NaN"
答案: C 扩展运算符(... args
)返回一个带参数的数组。 数组是一个对象,因此typeof args
返回object
。
10.下面代码的输出是什么?
class Chameleon {
static colorChange(newColor) {
this.newColor = newColor;
}
constructor({ newColor = "green" } = {}) {
this.newColor = newColor;
}
}
const freddie = new Chameleon({ newColor: "purple" });
freddie.colorChange("orange");
A: orange
B: purple
C: green
D: TypeError
答案: D 原因: Uncaught TypeError: freddie.colorChange is not a functioncolorChange
方法是静态的。 静态方法仅在创建它们的构造函数中存在,并且不能传递给任何子级。 由于freddie
是一个子级对象,函数不会传递,所以在freddie
实例上不存在colorChange
方法:抛出TypeError
。
9.下面代码的输出是什么?
function bark() {
console.log("Woof!");
}
bark.animal = "dog";
A: Nothing, this is totally fine! B: SyntaxError
. You cannot add properties to a function this way.
C: undefined
D: ReferenceError
答案: A 解释:var b = new bark(); console.log(b.animal); // undefined
11.下面代码的输出是什么?
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const member = new Person("Lydia", "Hallie");
Person.getFullName = () => this.firstName + this.lastName;
console.log(member.getFullName());
A: TypeError
B: SyntaxError
C: Lydia Hallie
D: undefined
undefined
答案: A member.getFullName is not a function
改写Person.prototype.getFullName = function () { }, 此时使用剪头函数, 输出为NaN
方式2,number.getFullName = function () { }, 可避免方法被添加至构造函数, 节约内存空间
12.下面代码的输出是什么?
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const lydia = new Person("Lydia", "Hallie");
const sarah = Person("Sarah", "Smith");
console.log(lydia);
console.log(sarah);
输出: Person {firstName: “Lydia”, lastName: “Hallie”} undefined
解释:对于sarah
,我们没有使用new
关键字。 使用new
时,它指的是我们创建的新空对象。 但是,如果你不添加new
它指的是全局对象!
13.下面代码的输出是什么?
function getPersonInfo(one, two, three) {
console.log(one);
console.log(two);
console.log(three);
}
const person = "Lydia";
const age = 21;
getPersonInfo`${person} is ${age} years old`;
A: Lydia
21
["", "is", "years old"]
B: ["", "is", "years old"]
Lydia
21
C: Lydia
["", "is", "years old"]
21
答案: B 解释: 如果使用标记的模板字符串,则第一个参数的值始终是字符串值的数组。 其余参数获取传递到模板字符串中的表达式的值!
14.下面代码的输出是什么?
const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);
obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1);
A: false
true
false
true
B: false
true
true
true
C: true
true
false
true
D: true
true
true
true
答案: C
15.下面代码的输出是什么?
const a = {};
const b = { key: "b" };
const c = { key: "c" };
a[b] = 123; // a: {[object Object]: 123}
a[c] = 456; // a: {[object Object]: 456}
console.log(a[b]);
A: 123
B: 456
C: undefined
D: ReferenceError
答案: B 原因:对象键自动转换为字符串, 变成了[Object object]
ES6
1. es6有哪些新特性, 这些新特性解决了哪问题?
- 新的变量声明方式:let和const。let声明变量作用在块级作用域
- 模版字符串,``包裹${}拼接。减少代码量增强可读性
- 新的函数声明方式:箭头函数。函数内部this指向函数上级
- 函数的参数默认值, function foo(name = ‘Jack’’)
- 解构赋值,[a, b] = [‘a’, ‘b’] 。独特的用例:交换两个变量的值。
- Spread / Rest 展运算符, […[1,2,3]] -> [1,2,3]。实现对数组的拷贝(concat()方法)
- iterable类型:Set与Map
- class类
- promoise
- 模块化, export\import
2. 给出[…”Lydia”]执行结果?
输出:[“L”, “y”, “d”, “i”, “a”]8.如何对数组去重?(常见六种)
- set […new Set(testData)]
- for-of + object 利用对象key不重复
- sort + for 排序后重复元素相邻
- for-of + includes
- filter + indexOf 过滤遍历全部数组, 过滤条件是第一次出现当前元素与当前索引不相等
testData.filter((d, index) => testData.indexOf(d) === index)
- for + for + splice
for (let i=0; i<res.length; i++) {
for (let j=i+1; j < res.length; j++) {
if (res[j] === res[i]) {
res.splice(j, 1)
j--
}
}
}
9.Promise.all
Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。10.实现promise
关于元编程的说法正确的是?(多选)
A.Reflect用于替代直接调用Object的方法
B.Reflect是一个函数对象,需要使用new操作符
C.Proxy用于自定义的对象的行为,比如修改set和get
D.Symbol、Reflect 和 Proxy 是属于 ES6 元编程范畴的,能“介入”对象的底层操作进行的过程中,并加以影响
答案:A C D
B:Reflect不是一个函数对象,没有constructor,所有不要使用new操作符
- es7有哪些新特性?
- Array.prototype.includes()
- 指数操作符, a ** b 等价于 Math.pow(a, b)
- es8有哪些新特性?
• async/await
• Object.prototype.values()\entries()
• String.prototype.padStart\padEnd
• 函数参数列表结尾允许逗号
• Object.getOwnPropertyDescriptors()
• SharedArrayBuffer对象
• Atomics对象 - es9有哪些新特性?
• 异步迭代
• Promise.finally()
• Rest/Spread 属性
• 正则表达式命名捕获组(Regular Expression Named Capture Groups)
• 正则表达式反向断言(lookbehind)
• 正则表达式dotAll模式
• 正则表达式 Unicode 转义
• 非转义序列的模板字符串 - es10有哪些新特性?
• 行分隔符(U + 2028)和段分隔符(U + 2029)符号现在允许在字符串文字中,与JSON匹配
• 更加友好的 JSON.stringify
• 新增了Array的flat()方法和flatMap()方法
• 新增了String的trimStart()方法和trimEnd()方法 // target_str = origin_str.replace(/^\s|\s$/g, “”)
• Object.fromEntries()
• Symbol.prototype.description
• String.prototype.matchAll
• Function.prototype.toString()现在返回精确字符,包括空格和注释
• 简化try {} catch {},修改 catch 绑定
• 新的基本数据类型BigInt
• globalThis
• import()
• Legacy RegEx
• 私有的实例方法和访问器
3.Symbol类型在实际开发中的应用、可手动实现一个简单的Symbol
- Symbol 值通过 Symbol 函数生成,使用 typeof,结果为 “symbol”
- Symbol 函数前不能使用 new 命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。
- instanceof 的结果为 false
- Symbol 函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
- 如果 Symbol 的参数是一个对象,就会调用该对象的 toString 方法,将其转为字符串,然后才生成一个 Symbol 值。
- Symbol 函数的参数只是表示对当前 Symbol 值的描述,相同参数的 Symbol 函数的返回值是不相等的。
- Symbol 值不能与其他类型的值进行运算,会报错。
- Symbol 值可以显式转为字符串。
- Symbol 值可以作为标识符,用于对象的属性名,可以保证不会出现同名的属性。
- Symbol 作为属性名,该属性不会出现在 for…in、for…of 循环中,也不会被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify() 返回。但是,它也不是私有属性,有一个 Object.getOwnPropertySymbols 方法,可以获取指定对象的所有 Symbol 属性名。
- 如果我们希望使用同一个 Symbol 值,可以使用 Symbol.for。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。
- Symbol.keyFor 方法返回一个已登记的 Symbol 类型值的 key。