共计 3474 个字符,预计需要花费 9 分钟才能阅读完成。
ES6 及以上最新标准
let 和 const
在 ES6 之前,申明变量的关键字只有var
,并且没有块级作用域,只有函数作用域和全局作用域。
let
、const
和 var
的区别
- 不容许申明晋升
- 不容许反复申明
- 不笼罩全局变量
- let
let 申明的变量,其申明语句不会再晋升。
console.log(outer);
console.log(inner); // Uncaught ReferenceError: inner is not defined
{console.log(outer); //
console.log(inner); // Uncaught ReferenceError: Cannot access 'inner' before initialization
var outer = true;
let inner = true;
console.log(outer); // true
console.log(inner); // true
}
console.log(outer); // true
console.log(inner); // Uncaught ReferenceError: inner is not defined
长期死区(Temporal Dead Zone, TDZ),也叫暂时性死区。用 let
或const
申明的变量,在申明前都会放到 TDZ 中,而申明前拜访这些变量就会触发运行时谬误。
其次,let 不容许反复申明同一个变量。这里有个限度:必须是在同一个作用域时,才不容许同一个变量反复申明。
最初是 let
在全局作用域中的个性。当用 var
在全局作用域中申明变量的时候,该变量岂但会成为全局变量,而且会成为全局对象(如浏览器中 window 对象)的一个属性。ES6 规定用 let 可将全局变量和全局对象断开分割。上面用两组代码别离演示断开分割(第一组)和笼罩已有属性(第二组),留神,在第二组代码中为了不便比照,疏忽了反复申明的谬误。
// group 1
var global = true;
console.log(window.global); // true
let whole = true;
console.log(window.whole); // undefined
// group 2
var Math = true;
console.log(window.Math); //true
let Math = true;
console.log(window.Math);
- const
const 岂但领有下面所述的 let 的 3 个个性,并且还能申明一个常量。常量是指一个定义了初始值后固定不变的只读变量。const
与 let
不同,申明时必须初始化(即赋值)。并且这设定后其值无奈更改。
留神,const 限度的是变量与内存地址之间的绑定。也就是说 const
让变量无奈更改内存地址。如果是根本类型(如布尔值、数字等)的变量,那么对应的内存地址中保留的就是值;如果是援用类型(如对象)的变量,那么对应的内存地址中保留的是指向理论数据的一个指针。由此可知,当用 const 申明的变量,其初始化的值是对象时,能够批改对象中的属性或办法。
- 循环中的
let
和const
ES6 规定了 let 申明在循环外部的行为,以 for 循环为例,
for (let i = 0; i < 3; i++) {setTimeout(function () {console.log(i);
}, 0);
}
在控制台输入的后果顺次为 0、1、2,没有呈现循环中的异步回调问题。这是因为在每次循环的时候,都会从新创立一个叫作 i 的同名变量,并将其初始化为计算后的值,而循环体内调用的 i 变量不会受其余同名变量的影响,所以可能在定时器的回调函数中正确显示该变量的值。在 ES5 及之前的版本中,如果要解决异步回调问题,能够借助立刻执行函数表达式(IIFE)能力失去预期的成果
for (var i = 0; i < 3; i++) {(function (n) {setTimeout(function () {console.log(n);
}, 0);
})(i);
}
Symbol
Symbol,能够像字符串那样作为对象的属性,且具备唯一性的特点,(重要)能够防止属性抵触。
1. 创立
Symbol
没有字面量模式,只能通过 Symbol()
函数创立。该函数有一个可选参数,只是用来形容以后符号,除了便于浏览,没有其余用处。即便 2 个 Symbol
的形容雷同,它们也不相等。Symbol()
不是构造函数,不能组合 new
运算符应用。
var sym1 = Symbol();
var sym2 = Symbol("name");
var sym3 = Symbol("name");
var sym4 = new Symbol(); // 抛出异样谬误
cosole.log(sym2 === sym3); // true
typeof
辨认Symbol
typeof Symbol() === "symbol"; // true
- 类型转换
Symbol 无奈与字符串和数字进行运算
var sym = Symbol("age");
Number(sym);
parseInt(sym);
1 + sym;
"" + sym;
但能够显性转成字符串或布尔值。
Boolean(sym); // true
!sym; // false
sym.toString(); // "Symbol(age)"
String(sym); // "Symbol(age)"
- 全局共享
ES6 会在外部保护一张全局符号注册表,通过 Symbol.for()办法,能够注销指定符号,使其变成一个全局无效的符号,从而达到全局共享。该办法只接管一个参数,这个参数既是注册表中的键值,同时也是此符号的形容。上面的代码调用了两次 Symbol.for()办法,传递了雷同的参数,返回的却是同一个全局符号。
var sym1 = Symbol.for("name");
var sym2 = Symbol.for("name");
console.log(sym1 === sym2); // true
- 属性名
常见三种属性名赋值形式:
- 内置符号
ES6 提供了一些内置符号,也叫出名符号(Well-Known Symbol)。它们裸露了语言的外部逻辑,容许开发人员批改或拓展标准所形容的 对象特色或行为。每一个内置符号对应 Symbol 对象的一个属性,如 Symbol.hasInstance、Symbol.iterator 等.
属性名称 | 值类型 | 形容 |
---|---|---|
hasInstance | 办法 | 当应用 instanceof 运算符,该办法会被调用 |
isConcatSpreadable | 布尔值 | 当对象作为 Array.protorype.concat()办法的参数时,管制改对象是否被开展 |
iterator | 办法 | 返回一个迭代器用于定义一个可迭代对象 |
match | 办法 | 当对象作为 String.prototype.match() 办法的参数时,该办法会被调用 |
replace | 办法 | 当对象作为 String.prototype.replace() 办法的参数时,该办法会被调用 |
search | 办法 | 当对象作为 String.prototype.search() 办法的参数时,该办法会被调用 |
split | 办法 | 当对象作为 String.prototype.split() 办法的参数时,该办法会被调用 |
species | 办法 | 创立派生类的构造函数 |
toPrimitive | 办法 | 当对象须要转换成原始值(即执行 toPrimitive 形象操作)时,该办法会被调用 |
toStringTag | 字符串 | 指定对象的类型,可在调用 Object.prototype.toString()办法的时候返回 |
unscopables | 对象 | 保留在这个对象中的属性将不能被 width 语句援用 |
上面给出 4 个内置符号示例:hasInstance
、isConcatSpreadable
、match
和toStringTag
:
- 实现一个可迭代的对象
var people = {
name: "test",
sex: "male",
hobbies: ["ball", "paint", "sing"],
[Symbol.iterator]() {
const _this = this;
const keys = Reflect.ownKeys(_this); // 获取到对象的 key 值列表
let index = 0;
return {next() {if (index < keys.length - 1) {
return {value: _this[keys[index++]], // 想返回什么 就返回什么 keys[index++]
done: false,
};
}
return {value: keys[index++],
done: true, // 迭代完结
};
},
};
},
};
for (let h of people) {console.log(h);
}