剑客
关注科技互联网

ES6 一些零碎的知识点

  • String.prototype.repeat(count):
    返回一个重复当前字符串若干次数的新字符串
varstr ='abc';
str.repeat(3);// abcabcabc
  • Number 对象

    • Number.parseInt(string[, radix]):
      根据给定的进制数把一个字符串解析成整数
    • Number.parseFloat(string):
      把一个字符串解析为一个浮点数
Number.parseInt ===parseInt// true
Number.parseFloat ===parseFloat// true
  • Math 对象

    • Math.trunc(value):
      将数字的小数部分去掉,只留整数部分
    • Math.cbrt(x):
      返回任意数字的立方根
    • Math.hypot([value1[,value2, …]]):
      返回它的所有参数的平方和的平方根
Math.trunc(12.02);// 12
Math.cbrt(27);// 3
Math.hypot(3,4);// 5

新的运算符

  • ES7 指数运算符:
    **
2**3;// 8
3**2;// 9
  • 扩展运算符

扩展运算符(spread)是三个点 ...
。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。

console.log(1, ...[2,3,4],5);// 1 2 3 4 5
vararr1 = [12,"hello"];
vararr2 = [false,"world"];
vararr3 = [...arr1, ...arr2];
console.log(arr3);// [12, "hello", false, "world"]

函数相关

  • 函数的 rest 参数(形式为“…变量名”):
    用于获取函数的多余参数,这样就不需要使用arguments对象了

rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

// test 1
functionf1(...values){
console.log(values);// [1, 2, "percy", true]
}
f1(1,2,"percy",true);

// test 2
functionf2(num1, ...values){
console.log(num1);// 1
console.log(values);// [2, "percy", true]
}
f2(1,2,"percy",true);

// test 3
// rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错
functionf3(num1, ...values, bool){// 报错,Uncaught SyntaxError: Rest parameter must be last formal parameter
console.log(num1);
console.log(values);
console.log(bool);
}
f3(1,2,"percy",true);

对象相关

  • 更简洁的对象字面量写法

ES6允许直接写入变量和函数,作为对象的属性和方法。

// 属性
letname ="percy";
letage =21;
// 方法
letsayName =function(){
console.log(this.name);
};
letsayAge = () => {console.log(this.age); };

// 创建对象
letuser = {
 name,
 age,
 sayName,
 sayAge,
 sayAll() {
console.log(`name:${this.name},age:${this.age}`);
 }
};

console.log(user);// Object {name: "percy", age: 21}
user.sayName(); // percy
user.sayAge(); // undefined
// 要是不理解上一行为什么是 undefined,可以去看看箭头函数是如何对待 this 的
user.sayAll(); // name:percy,age:21
  • 属性名表达式
letobj = {
// // ES6 新增写法
 [1+2+'a'+'b']:"hell"
};

// 传统写法
obj.foo = true;

// ES6 新增写法
obj['a'+'bc'] =123;

console.log(obj);// Object {3ab: "hell", foo: true, abc: 123}
  • Object.is(value1, value2):
    用来判断两个值是否是同一个值

传统的两种相等比较有一些缺陷

  • ==
    :先对它两边的操作数做隐式的类型转换,再进行比较
  • ===
    :认为 +0 和 -0 相等,NaN 和 NaN 不相等

而 Object.is() 就是为弥补这些缺陷设计出来的!

""==false;// true
Object.is("",false);// false

+ 0===-0;// true
NaN===NaN;// false
Object.is(+0,-0);// false
Object.is(NaN,NaN);// true
  • Object.assign(target, …sources):
    把任意多个的源对象 自身的可枚举
    属性 浅拷贝
    给目标对象,然后返回目标对象
letperson1 = {
 name1: "percy",
 age1: "21",
 isStudent: true
};

// 设置 age1 属性为不可枚举
Object.defineProperty(person1,"age1", { enumerable:false});

letperson2 = {
 name2: "zyj",
 age2: 22,
 sayName: function(){
console.log(this.name2);
 }
};

// 设置 sayName 属性(或方法)为不可枚举
Object.defineProperty(person2,"sayName", { enumerable:false});

letperson3 = {
 name3: "bob",
 age3: 23,
 sayAge: function(){
console.log(this.age3);
 }
}

letpersons =Object.assign({ name:"persons"}, person1, person2, person3);

console.log(persons);
// persons = {
// age2: 22,
// age3: 23,
// isStudent: true,
// name: "persons",
// name1: "percy",
// name2: "zyj",
// name3: "bob",
// sayAge: function() {
// console.log(this.age3);
// }
// }

Object.assign 方法实行的是 浅拷贝
,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

// 继续上面的代码
persons.sayAge === person3.sayAge; // true
  • ES6 中,共有 5 种方法可以遍历对象的属性

    • for…in:
      循环遍历对象自身的和继承的可枚举属性(不含 Symbol 类型的属性)
    • Object.keys(obj):
      返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 类型的属性)
    • Object.getOwnPropertyNames(obj):
      返回一个数组,包含对象自身的所有属性(不含 Symbol 类型的属性,不包含继承属性,但是包括不可枚举属性)
    • Object.getOwnPropertySymbols(obj):
      返回一个数组,包含对象自身的所有 Symbol 类型的属性(不包括继承的属性)
    • Reflect.ownKeys(obj):
      返回一个数组,包含对象自身的所有属性(包含 Symbol 类型的属性,还有不可枚举的属性,但是不包括继承的属性)

以上的5种方法遍历对象的属性,都遵守同样的属性遍历的次序规则

  • 首先遍历所有属性名为数值的属性,按照数字排序
  • 其次遍历所有属性名为字符串的属性,按照生成时间排序
  • 最后遍历所有属性名为Symbol值的属性,按照生成时间排序

从 ES6 起,对象的属性名有两种类型: 一种是原来就有的字符串
另一种就是新增的Symbol类型
。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

// 为 obj 设置 2 个继承属性
Object.prototype.inherit1 ="inherit111";
Object.prototype[Symbol('inherit2')] ="inherit222";

// a,b 为 Symbol 类型的属性名
leta =Symbol('a');
letb =Symbol('b');

letobj = {
 [a]: 'aSymbol',
 [b]: 'bSymbol',
 name: "percy",
 age: 20,
 c: "cEnumFalse",
 d: "dEnumFalse"
};

// 设置 c,d 为不可枚举的属性
Object.defineProperties(obj, {
 c: { enumerable: false},
 d: { enumerable: false}
});

// test 1
vararr = [];
for(letvalueinobj) {
 arr.push(value);
 }
console.log(arr);
// ["name", "age", "inherit1"]

// test 2
console.log(Object.keys(obj));
// ["name", "age"]

// test 3
console.log(Object.getOwnPropertyNames(obj));
// ["name", "age", "c", "d"]

// test 4
console.log(Object.getOwnPropertySymbols(obj));
// [Symbol(a), Symbol(b)]

// test 5
console.log(Reflect.ownKeys(obj));
// ["name", "age", "c", "d", Symbol(a), Symbol(b)]
  • 谈谈 __proto__ 属性

__proto__属性(前后各两个下划线), 用来读取或设置当前对象的 prototype 对象(原型对象)
,该属性没有写入 ES6 的正文,而是写入了附录,原因是 __proto__ 前后的双下划线,说明它本质上是一个内部属性,而不是一个正式的对外的API,只是由于浏览器广泛支持,才被加入了 ES6。标准明确规定,只有浏览器必须部署这个属性,其他运行环境不一定需要部署,而且新的代码最好认为这个属性是不存在的。因此, 无论从语义的角度,还是从兼容性的角度,都不要使用这个属性
,而是使用下面的 Object.setPrototypeOf()
(写操作)、 Object.getPrototypeOf()
(读操作)、 Object.create()
(生成操作)代替。

  • Object.getPrototypeOf(object):
    (ES 5.1)返回指定对象的原型对象
  • Object.setPrototypeOf(obj, prototype):
    (ES 6)将一个指定的对象的原型设置为另一个对象或者null
  • Object.create(proto, [ propertiesObject ]):
    (ES 5.1)创建一个拥有指定原型和若干个指定属性的对象
    • 注意:
      上面这个函数的第二个参数要与 Object.defineProperties()
      的第二个参数保持一致,否则报错
letobj = {
 name: "percy",
 age: 20
};
letobjProto = {
 where: "objProto",
 sayName: function(){
console.log(this.name);
 }
};

console.log(Object.getPrototypeOf(obj));// Object {}
console.log(Object.getPrototypeOf(objProto));// Object {}

Object.setPrototypeOf(obj, objProto);
Object.setPrototypeOf(objProto,null);

console.log(Object.getPrototypeOf(obj));// Object {where: "objProto"}
console.log(Object.getPrototypeOf(objProto));// null

letcreateObj =Object.create(objProto, { name: { value:"I am create!"} });
createObj.sayName(); // I am create!
分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址