ECMAScript6

简介

ES6目标,让JavaScript变成一个企业级的开发语言,不仅仅限制与前端页面的脚本语言。

编译

服务端使用 babel 编译

构建工具fis使用
插件:fis-parser-babel2 编译ES6

fis.match(' .ts', {    parser: fis.plugin('babel2'),    rExt: '.js'});

TypeScript与babel编译有区别:

例如:对一个类的编译TypeScript编译的结果是一个闭包类,babel编译的结果是一个安全类.

function _classCallCheck( instance, Constructor ) {     if (!(instance instanceof Constructor)) {         throw new TypeError("Cannot call a class as a function");     } }var Person = function Person() {    _classCallCheck(this, Person);};

浏览器端编译traceur库来编译.

traceur库,引入两个库:traceur.js 和 treaceur-bootstrap.js

写的ES6中,需要指定type类型为module
注意: 需要写在引入库的后边。

    class Person {    }    console.log(Person);

let&const

let

let声明一个块级作用域,并且可以初始化该变量。用法与var类似。只能在所在的代码块内有效。

块作用域:{}构成的一个代码库处的作用域叫做块作用域。

let 允许吧变量的作用域限制在块级域中。与var 不同的是:var声明变量要么是全局的,要么是函数级的,而无法是块级的。

典型应用:for循环中的计数器
let定义的变量,会在块作用域保留下来,访问的就是当前循环的变量值。

for ( let j=0; j

for(let i = 0; i

function foo(){  a = 20;  // 报错 ReferenceError  console.log(a);  let a = 10;  console.log(a);}foo();

let 的暂存死区

在同一个函数或同一个作用域中的let重复定义一个变量将引入TypeError

注意:switch中声明的变量。

if ( true ) {    let a;    let a; // TypeError thrown.}

如果块中存在let 和const。 凡是在声明之前就使用这些变量,就会报错。
let声明之前,该变量都是不可用的。称之为:暂时性死区(temproal dead zone简称 TDZ)

if (true) {  // TDZ开始  a = 10; // ReferenceError  console.log(tmp); // ReferenceError  let a; // TDZ结束  console.log(tmp); // undefined  a = 100;  console.log(tmp); // 100}

ES6中的TDZ 像是运行时的检查而不是语法声明上的概念.

if(true){    setTimeout(function(){        console.log(x); // 1    });    let x = 1;}

let特点:

  1. 具有块级作用域

  2. 没有变量提升

  3. 不允许重复声明

  4. 具有暂时性死亡区

为了不出发死亡区,必须,变量先声明,后使用的规定。
let声明的全局变量并不是全局对象的属性
let声明的变量知道控制流到达该变量被定义的代码行时才会被装载,所以在到达之前会使用该变量会触发错误,也就是所说的暂时性死亡区。没有分为预解析阶段。

块级作用域的意义:
ES5中,只有全局作用域和函数作用域,没有块级作用域。

缺点:
1:内存变量可能会覆盖外层变量。
2:用来计数的循环变量泄漏为全局变量。(循环内变量过度共享)

const

const声明一个只读的常量。 一旦声明,常量的值就不可更改。
意味着,const一旦声明常量,就必须立即初始化,不可留到以后赋值。

语法:const key = value;

在定义常量的前面,不能访问到常量,因此一般都将常量定义在文件的最前面。
例如:require() 模块的时候使用。

const http = require('http');

常量不能被重复定义,为了保证常量定义使用的时候的安全性。

const 和 let 的区别:
const具有let的所有特性,比let更加严格,不可以被重复定义(赋值)。

const 只是保证变量名指向的地址不变,并不保证该地址的数据不变。所以将一个对象声明为常量必须非常小心。

const foo = {};foo.k1 = 100;console.log( foo.k1 );foo = {}; // TypeError: "foo" is read-only// 常量foo 储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但是对象本身是可变的,所以依然可以为其添加新的属性。

Objcet.freeze()
作用:冻结对象(不可为对象添加属性和和方法)
参数:被冻结的对象

const foo = {}Object.freeze(foo);// 常规模式时,下面一行不起作用, 忽略添加 // 严格模式时,该行会报错foo.k1 = 100;console.log(foo);

解构赋值

数组的结构赋值

解构:从数组和对象中提取值,对变量进行赋值。

基本用法:

let [a, b, c] = [1, 2, 3]; // 从数组中提取值,按照对应位置,对变量赋值。// 这种写法,本质上属于“模式匹配”。 只要等号两边的模式相同,左右的变量就会赋予对应的值。let [foo, [[bar], baz]] = [1, [[10], 100]];let [x, y, ...z] = ['a', 'b', 'c', 'd'];console.log(x,y,z); // a b ["c", "d"]

如果解构不成功,变量值为undefiend。

let [d] = []; // undefinedlet [e, f] = [1]; // 1 undefined

不完全解构: 等号左边的模式,只匹配一部分等号右边的数组。

let [x, y] = [1, 2, 3];console.log(x, y); // 1  2let [a, [b], c] = [1, [2, 3], 4];console.log(a, b, c); // 1 2 4

等号的右边不是数组,(严格的说,不是可遍历的结构),会报错。

// 报错let [foo] = 1;let [foo] = false;let [foo] = NaN;let [foo] = undefined;let [foo] = null;let [foo] = {};// 转为对象以后不具备Iterator接口(前面5个表达式), 本身就不具备Iterator接口(最后一个表达式) 

只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。 (例如:函数执行之后的返回值)

默认值
解构赋值允许设置默认值

let [a = 100] = [];console.log(a); // 100

ES6内部使用严格相等 运算符(===),判断一个位置是否有值。如果一个数组成员不严格等于undefeind,默认值不会生效。

let [a = 1] = [undefined];let [b = 10] = [null];let [c = 100] = [NaN];console.log(a, b, c); // 1 null NaN

如果默认值是一个表达式,这个表达式是惰性求值(只有在用到的时候才会求值)。

function fn () {    console.log('a');}let [x = fn()] = [1];console.log(x); // 1 // fn(); 函数不会执行

默认值可以引用其它解构赋值的变量
默认值可以引用解构赋值的其它变量,但该变量必须已经声明,如果不声明,将会报错。

let [x = 1, y = x] = []; // x = 1  y = 1let [x = y, y = 1] = []; // ReferenceError // x用到默认值y时,y还没有声明。

最为常用的地方是:函数参数的arguments类数组对象的解构赋值。

对象的解构赋值

对象的解构与数组有一个重要的不同之处,数组的元素是按次序排序,变量的取值由它的位置决定的,而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

let {a, b} = {b: 10, a: 100}; console.log(a, b); // 10  100let { c } = {d: 1000, e: 100 }console.log(c); // undefined

对象的解构赋值的内部机制:先找到同名属性,然后再赋值给对应的变量。真被赋值的是后者,而不是前者。

let {foo: baz} = {foo: 'aaa', bar: 'bbb'}console.log(baz); // aaaconsole.log(foo); // ReferenceError// 被赋值的是变量baz,而不是模式foo

默认值

默认值生效的条件:对象的属性值严格等于undefined。

let {x = 3} = {x: undefined}// x = 3;let {y = 10} = {y: null}console.log(x, y); // 3 null

如果解构失败,变量值等于undefined

字符串的解构赋值

字符串的解构赋值本质:字符串被转为类数组对象,类数组对象中有length属性,可以有Iterator接口,可以被遍历。

const [a, b, c, d, e] = 'hello';console.log(a, b, c, d, e); // h e l l o

数值和布尔值的解构赋值

需要指定包装对象toString
解构规则:等号右边的值不是对象,就先将其转为对象。 undefind 和 null 无法转为对象,对其二者解构赋值,都会报错。

let {toString: s} = 10;console.log( s === Number.prototype.toString ); // trueconsole.log(s);  // function toString() { [native code] }let { toString: t } = true;console.log(t); // function toString() { [native code] }

函数参数解构赋值

可以解构赋值,可以使用默认值

[[1, 2], [3, 4]].map( ([a, b]) => a + b ); // 3 7[[, 2], [, 4]].map(function ( [a = 10, b] ) {    return a + b;}); 

圆括号问题

对于编译器来说,一个式子到底是模式,,还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道。
问题:模式中出现的圆括号怎么处理。
解析规则:只要有可能导致解构的歧义,就不得使用圆括号。

建议:只要有可能,就不要再模式中放置圆括号。能不使用,就不使用圆括号。

不能使用圆括号的情况

变量声明语句中,不能带有圆括号

// 全部报错var [(a)] = [1];var {x: (c)} = {};var ({x: c}) = {};var {(x: c)} = {};var {(x): c} = {};}var { o: ({ p: p }) } = { o: { p: 2 } };// 都是变量声明语句,模式不能使用圆括号。

函数参数中,模式不能带有圆括号。

// 报错function f([(z)]) { return z; }    

赋值语句中,不能将整个模式,或嵌套模式中一层,放在圆括号之中。

// 全部报错({ p: a }) = { p: 42 };([a]) = [5];

可以使用圆括号的情况:
赋值语句的非模式部分,可以使用圆括号。

[(b)] = [3]; // 正确  // 模式是取数组的第一个成员,跟圆括号无关({ p: (d) } = {}); // 正确 // 模式是p,而不是d;[(parseInt.prop)] = [3]; // 正确 // 模式是取数组的第一个成员,跟圆括号无关

用途

交换变量的值

[x, y] = [y, x]

从函数返回多个值

函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。

// 返回一个数组function example() {  return [1, 2, 3];}var [a, b, c] = example();// 返回一个对象function example() {  return {    foo: 1,    bar: 2  };}var { foo, bar } = example();

函数参数定义

将一组参数与变量名对应。

// 参数是一组有次序的值function f([x, y, z]) { ... }f([1, 2, 3]);// 参数是一组无次序的值function f({x, y, z}) { ... }f({z: 3, y: 2, x: 1});

提取JSON数据

提取JSON对象中的数据

函数参数的默认值

遍历Map结构

输入模块的指定方法

加载模块时,往往需要指定输入那些方法。

const { SourceMapConsumer, SourceNode } = require("source-map");

String的扩展

satrtsWith

str.starsWith(str1, num);

判断字符串以指定参数开头
参数1:开头的字符
参数2:可选,指定开始查找的索引位置
返回布尔值

endWith

str.endWith(str1, num);

判断字符串以指定参数结束
参数1:结束的字符子串
参数2:可选,指定开始查找的索引位置
返回布尔值

includes

str.includes(str1, num);

判断指定的参数字符串是否包含在字符串中。
参数1:被查询的字符串
参数2:可选,从那边开始查找索引位置。
返回布尔值

标签模板

``可以紧跟一个函数名后边,该函数将被调用来处理这个模板字符串。 称之为:“标签模板”(tagged template);

alert`123`;alert(123);  // 等同

标签模板实质并不是模板,而是函数的调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。

如果模板字符里面有变量,就不在是简单的调用,而是会将模板字符串先处理成多个参数,再调用函数。

模板字符串

语法:${表达式}
需要通过``来声明字符串,才会生效。
如果使用''单引号声明没有效果。并不会解析模板中的表达式。

//let num = `十`;let num = `5`;let intro = `# 笑一笑,${5 * 2}年少`;

repeat

重复字符串
参数:指定重复的次数

let num = '10';let intro = `# 笑一笑,${num * 2}年少`;let introT = intro.repeat(2);console.log(intro);console.log(introT);

raw

返回原始字符串,该方法不会将字符串中的转义字符转义
这个方法特殊,不需要使用()调用.
是String底下的一个方法,直接通过String调用即可。

console.log('success \n 1');let str = String.raw`success \n 1`;console.log(str);

Number的扩展

ES6在Number对象上,提供了Number.isFinite() 和 Number.isNaN();两个方法。
用来检查Infinite和NaN这两个特殊值。

isFanite();

检查是否是作为数字存在,对于不存在或者是NaN返回值为:false,对于数字返回值为:true

Number.isFinite(15); // trueNumber.isFinite(0.8); // trueNumber.isFinite(NaN); // falseNumber.isFinite(Infinity); // falseNumber.isFinite(-Infinity); // falseNumber.isFinite('foo'); // falseNumber.isFinite('15'); // falseNumber.isFinite(true); // false
// 实现方式(function (global) {  var global_isFinite = global.isFinite;  Object.defineProperty(Number, 'isFinite', {    value: function isFinite(value) {      return typeof value === 'number' && global_isFinite(value);    },    configurable: true,    enumerable: false,    writable: true  });})(this);

isNaN();

当参数是NaN的时候,才返回true,其它情况都返回false。

Number.isNaN(NaN) // trueNumber.isNaN(15) // falseNumber.isNaN('15') // falseNumber.isNaN(true) // falseNumber.isNaN(9/NaN) // trueNumber.isNaN('true'/0) // trueNumber.isNaN('true'/'true') // true
// 实现方式(function (global) {  var global_isNaN = global.isNaN;  Object.defineProperty(Number, 'isNaN', {    value: function isNaN(value) {      return typeof value === 'number' && global_isNaN(value);    },    configurable: true,    enumerable: false,    writable: true  });})(this);

与传统的全局方法isFinte()方法isNaN()的区别:
传统方法先调用Number()将非数值的值转为数值,再进行判断。
Number.isFinte()和isNaN();只对数值有效,非数值一律返回false.

parseInt&parseFloat

ES6将全局方法parseInt();和parseFloat();方法 移植到Number对象上,行为完全保持不变。

目的:逐渐减少全局性方法,是的语言逐步模块化。

isInteger

当参数是正整数,负整数,0,-0,的时候返回值为:true。其它情况下返回值为:false
在JavaScript内部,整数和浮点数使用同样的存储方法,所以3和3.0被视为同一个值。

Math的扩展

sign

Math.sign();用来判断一个数到底是整数,负数,还是零。
返回值:

  1. 参数为整数,返回+1

  2. 参数为负数,返回-1

  3. 参数为0 ,返回0

  4. 参数为-0,返回-0

  5. 参数为其它值,返回NaN

Math.sign(''); // NaNMath.sign('a'); // NaN Math.sign(NaN); // NaNMath.sign(false); // NaNMath.sign(undefined); // NaNMath.sign(0); // 0Math.sign(-0); // -0Math.sign(-2); // -1Math.sign(+2); // 1
// 模拟 Math.sign(); 方法Math.sign = Math.sign || function ( x ) {    x = +x;    if ( x === 0 || isNaN(x) ) {        return x;    }    return x > 0 ? 1 : 1;}

trunc

Math.trunc(); 用于去除一个数的小数部分,返回 整数部分。

非数值,Math.trunc()内部先使用Number();将其转为数值。

Math.trunc(123.456); // 123

对于空值和无法截取整数的值,返回NaN

Math.trunc(NaN); // NaNMath.trunc('hello'); // NaN// 模拟Math.trunc();Math.trunc = Math.trunc || function ( x ) {    return x 

let arrayLike = {
0: 'a',
1: 'b',
length: 2
}

// ES6的写法
let arr2 = Array.from(arrayLike, function ( value, index ) {

return value + '-xixi';

});

## ofArray.of();将一组值,转为数组。返回值:返回参数值组成的数组,如果没有参数,就返回一个空数组。作用:弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有所差异。Array()如果是一个参数,则表示当前数组的长度。如果是二个或二个以上,则表示数组成员。

Array.of(1, 2, 3, 'xixi');

Array.of();基本上可以用来替代Array()或new Array(); 并且不存在由于参数不同而导致的重载问题。

Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]

// 模拟Arraay.of();方法
function ArrayOf () {
return [].slice.call(arguments);
}

## findfind();方法和findIndex();方法find();作用:获取第一个符合条件的数组成员。参数:回调函数。所有的数组成员一次执行该回调函数。知道找出一个返回值为true的成员。如果没有符合条件的成员,则返回false。回调函数中的参数: 当前value值,当前索引值index(可选), 原数组arr(可选)

[1, 2, 23, 10].find( (n) => n > 10 ); // 23
[1, 2, 3].find( ( value, index, arr ) => value Object.is('tan', value) );

提出的解决问题:indexOf();无法检测出成员中是否有NaN

[NaN].indexOf(NaN); // -1

findIndex();搭配 Object.is(); 可以检测出来

[10,NaN].findIndex( (value) => Object.is(NaN, value) ); // 1

## fill使用给定值,填充一个数组。    参数1:填充的值参数2:可选,填充的起始位置。参数3: 可选,填充的结束位置。## keyskeys() & values(); & entrices();keys();获取数组所有成员的索引值。返回的是一个迭代器对象。需要通过 for-of遍历数组迭代器

let colors = ['cyan', 'pink', 'tan', 'red'];

let Idx = colors.keys();

console.log( Idx ); // ArrayIterator {}

for ( let index of Idx ) {

console.log(index);

}

values();获取所有成员的值,返回一个数组迭代器对象。

let colors = ['cyan', 'pink', 'tan', 'red'];

let vals = colors.values();

console.log( vals ); // ArrayIterator {}

for ( let val of vals ) {

console.log(val);

}

entries();对键值对的遍历。将数组成员的索引值以及数组成员的值,保留在一个新数组中。

let colors = ['cyan', 'pink', 'tan', 'red'];

let entri = colors.entries();

console.log(entri);

for ( let entris of entri ) {

console.log( entris );

}
// 输出:
// [0, "cyan"]
// [1, "pink"]
// [2, "tan"]
// [3, "red"]

如果不使用for-of遍历,可以手动调用遍历器对象的next();方法,进行遍历。

let colors = ['cyan', 'pink', 'tan', 'red'];

let entri = colors.entries();

console.log( entri.next().value ); // [0, "cyan"]
console.log( entri.next().value ); // [1, "pink"]
console.log( entri.next().value ); // [2, "tan"]
console.log( entri.next().value ); // [3, "red"]

// next();方法返回:Object {value: Array[2], done: false}

## 空位数组的空位:数组的某一个位置没有任何值。例如:Array构造函数返回的数组都是空位。空位不是undefined,一个位置的值等于undefined,依然是有值的。空位是没有任何值注意:空位不是undefiend,一个位置的值等于undefeind。依然是有值。空位是没有任何值。

0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false
// 第一个数组的0号位置是有值的,第二个数组的 0 号位置没有值。

ES5中对于空位的不一致:1. forEach(), filter(), every() ,some()都会跳过空位。1. map()会跳过空位,但会保留这个值1. join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串。

// forEach();
[,'a'].forEach((x,i) => console.log(i)); // 1

// filter();
['a',,'b'].filter(x => true) // ['a','b']

// every();
[,'a'].every(x => x==='a') // true

// some();
[,'a'].some(x => x !== 'a') // false

// map();
[,'a'].map(x => 1) // [,1]

// join();
[,'a',undefined,null].join('# ') // "# a## "

// toString();
[,'a',undefined,null].toString() // ",a,,"

ES6则明确将空位转成undeinfed由于空位的处理规则非常不统一,所以应该尽量避免出现空位。# Object的扩展## 属性的简洁表示ES6允许直接写入变量和函数,作为对象的属性和方法。在定义一个对象的时候,如果对象的属性与属性值对应的变量名同名,可以简写属性名。

let objName = 'bar';
let obj1 = {objName}

console.log( obj1 ); // Object {objName: "bar"}

// 等同于
let obj2 = {objName: objName} // Object {objName: "bar"}
console.log(obj2);

// 在对象之中,只写属性名,不写属性值,这时候,属性值等于属性名所代表的变量。

// 参数简写
function Person ( name, age ) {
return {name, age} // ES6 允许直接引入变量,不用对对象添加同名属性
}

console.log( Person('cyan', 22) ); // Object {name: "cyan", age: 22}

// 等同于
function Person(name , age) {
return {name: name, age: age};
}

// 方法的简写
// 如果对象属性名与对象属性名对应的方法名称相同,可以省略属性以及 function关键字, 像定义类中的方法一样定义这个属性方法。

let obj1 = {
name: 'cyan',
age: 22,
sayAge: function () {
console.log(this.age); // 22
},
sayName () { // ES6允许定义方法的时候,可以省略方法对应的属性名,和 fucntion 关键字
console.log(this.name); // cyan
}
}

obj1.sayName();
obj1.sayAge();

// sayName等同于

var obj1 = {
sayName: function() {
console.log(this.name);
}
}

// 这种属性简写用于函数返回非常方便
function getPoint() {
var x = 1;
var y = 10;
return {x, y};
}

getPoint();
// {x:1, y:10}

## 属性名表达式JavaScript语言定义对象的属性,有两种方式。

// 方法一
obj.foo = true; // 标识符作为属性名

// 方法二
obj['a' + 'bc'] = 123; // 表达式作为属性名

// 允许定义对象时候,对对象属性应用表达式
let a = 'num';
let b = 'ber';

let obj = {

}

console.log( obj );

// 表达式也可以用于方法名
let obj = {
['h'+'ello']() {
return 'hi';
}
};

obj.hello() // hi

注意:属性名表达式不能与简洁表示法同时使用,会报错。

// 报错
let a = 'b';
let b = 'pink';
let color = { [a] }

console.log(color);

// 正确
let a = 'cyan';
let color = { [a]: 'pink' }

console.log(color);

## 方法的name属性函数的name属性,返回函数名。对象方法也是函数,,因此也有name属性。

let obj = {
name: 'cyan',
sayName() {
return this.name;
}
}

console.log( obj.sayName.name ); // sayName

特殊:bind();方法创造的函数,name属性返回"bound"加上原函数的名字。Function构造函数创造的函数,name属性返回"anonymous".

console.log( (new Function()).name ); // anonymous

let doSomething = function () {}

console.log( doSomething.bind().name ); //bound doSomething

## isObject.is();作用判断两个参数是否相等。 可以判断0与-0 ,是否相等。ES5中,比较两个值是否相等使用:==或者===   ==缺点:自动转换数据类型===缺点:NaN不等于自身,以及0等于-0ES6提出“Same-value equality”(同值相等)算法.用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

## assginObject.assgin();作用:用于对象合并。    将源对象(source)的所有可枚举属性,复制到目标对象(target)。参数1:目标对象。后面的参数都是源对象。只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。如果只有一个参数对象,则返回该参数对象。

let obj1 = {
x: 1,
y: 2
}

let obj2 = {
a: 'a',
b: 'b'
}

console.log( Object.assign(obj1, obj2) );

如果参数不是对象,则会先转成对象然后返回。undefeind和null无法转成对象,作为参数,会报错。

Object.assign(2); // Number {[[PrimitiveValue]]: 2}
Object.assign(undefined) // 报错
Object.assign(null) // 报错

Object.assign();是浅拷贝,而不是深拷贝。如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

let obj1 = {a: {b: 1}};
let obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b // 2

## 属性遍历ES6中共有5中可以遍历属性的方法:1. for-in

for-in循环遍历对象吱声和继承的可枚举的属性(不含Symbol属性)。

1. Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承)所有可枚举属性(不含Symbol属性)

1. Oject.getOwnPropertyNames(obj);

Object.getOwnPropertyNames(); 返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)

1. Object.getOwnPropertySymbols(obj);

Object.getOwnPropertySymbols();返回一个数组,包含对象自身的所有Symbol属性。

1. Reflect.ownKeys(obj);

Reflect.ownKeys(obj);返回一个数组,包含对象自身的所有属性,不管是属性名Symbol或字符串,也不管是否可枚举

遍历规则:1. 首先遍历所有属性为数值的属性,按照数字排序。1. 其次遍历所有属性名为字符串的属性,按照生成时间排序。1. 最后遍历所有属性名为Symbol值的属性,按照生成时间排序。#es6、JavaScript#

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部