4

这里仅列出大家容易忽略的知识点,用于查缺补漏~

Symbol

原始数据类型,由Symbol函数生成。

//正确.返回具有唯一性的值
Symbol()
Symbol(label)

//错误
//因为返回的是原始类型;同undefined;null;Boolean;String;Number;
//对象(Object、Array、Function)是引用数据类型。
new Symbol()  

不能做字符串拼接等运算操作,但可以显示转换为字符串:Symbol().toString() //"Symbol()".
应用:
1.作为对象属性

//获取Symbol的方法:
Object.getOwnPropertySymbols(obj) //获取对象的Symbol属性名
Reflect.ownKeys(obj) //获取对象自身所有属性,包括不可枚举以及Symbol

可以在封装对象时,将Symbol用作非私有,但只用于内部访问的属性。(挂在对象上,但外部拿不到Symbol值就无法访问其对应的值)。
2.作为常量值
3.Symbol.for(label)
全局登记的方式,只有未找到的情况下才会返回新的Symbol值;利用其全局环境搜索的这个特性,可以跨iframe获取值。
4.内置Symbol值
执行对象(Object或String等)原型上特定的内部方法时,会自动执行对象对应的Symbol对应的函数。
举两个典型的例子:

1. Symbol.iterator
- 其值为对象的遍历器对象生成器
- 当使用for...of()循环时,会自动调用对象的Symbol.iterator方法
//for...of ES6提供的统一的访问数据结构的接口

2. Symbol.toStringTag   
//使用Object.prototype.toString方法,会先找对象的Symbol.toStringTag
({[Symbol.toStringTag]: 'M2'}).toString();  //"[object M2]"

Proxy | Reflect

ES6 为操作【对象】而提供的新 API。
Reflect

  • 内部方法:Proxy this问题 Reflect解决
  • 对象操作,部分命令式操作变成函数行为,如:delete obj.attr变为Reflect.deleteProperty(obj, attr)
  • 和Proxy方法一一对应

Set | Map

特性:
set:保证值的唯一性;去重。
map: 相对于对象,是一种更完善的hash结构实现。

适用使用for...of实现遍历的各种场景,如扩展运算符等。
Map 结构的默认遍历器接口(Symbol.iterator属性),就是entries方法。

map[Symbol.iterator] === map.entries

Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。

Set.prototype[Symbol.iterator] === Set.prototype.values

WeakSet | WeakMap

  • 只接受对象作为键名;
  • 弱引用,不计入垃圾回收;防止内存泄漏,但也导致不支持遍历和size。

用途:1)dom元素的记录or操作 2)私有方法 | 私有属性

Object

1.比较两个值是否完全相同
//除了+0和-0不等;NaN等于自身。别的等同于===
Object.is(a,b) 

2.对象的合并;之拷贝对象自身可枚举的属性
//原始类型会被转换成对象
Object.assign(2)  //Number{2}
//原始类型只有字符串可以被拷贝到对象上,因为其可遍历(结合iterator理解)
Object.assign({}, 2, '3');  //{0: "3"}
//数组的替换
Object.assign([1,2,3], [4,5]) //[4,5,3]

3.设置|获取对象原型
Object.setPrototypeOf(target, prototype);
Object.getPrototypeOf(target);

4.遍历
Object.keys()
Object.values()
Obeject.entries() //对象转键值对数组

5.键值对数组转对象
Object.fromEntries() //entries的逆操作;因此适合将Map结构转为Object
Object.getOwnPropertyDescriptors()

返回指定对象所有自身属性(非继承属性)的描述对象。

主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题。getOwnPropertyDescriptors不仅会返回对象属性,而且包括其属性描述器。
obj={a:'a',b:'b'}
Object.getOwnPropertyDescriptors(obj);
//output:
{
    a:{value:"a",writable:true,enumerable:true,configurable:true}
    b:{value:"b",writable:true,enumerable:true,configurable:true}
}

应用:可以结合Object.assignObject.create

Object.create(proto[, propertiesObject])

作用:创建一个新对象,使用已有对象作为新创建对象的__proto__;
propertiesObject可选,默认为创建对象的自有属性;

o = Object.create({a:1}, {
    foo: { 
        value: "hello" 
  }
})
o.hasOwnProperty('foo') //true  

省略了的属性特性默认为false,所以属性foo是不可写(writable)、不可枚举(enumerable)、不可配置(configurable)。
常见示例:

  • 创建空对象
1. obj = {};
  等价于
  obj = Object.create(Object.prototype);

2. obj = Object.create(null); //创建一个原型为null的空对象
  • 子类继承父类时使用
// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);
/*
* 等价于
* function prototypeCerate(o) {
*   function F() {}
*   F.prototype = o;
*   return new F();
* }
* Rectangle.prototype = prototypeCerate(Shape.prototype);

*/

Rectangle.prototype.constructor = Rectangle;

super

指向当前对象的原型对象;【作为构造函数 | 原型对象】

//指向原型对象时,只能用在对象方法中,如下:
const obj = {
  getName() { super.getName(); }
}
//错误. super被用在普通函数里面,该函数被赋值给getName。
const obj = {
  getName: () => super.getName()
}

内部原理:

super.foo
//1.作为原型属性:
Object.getPrototypeOf(this).foo
//2.作为原型方法:
`bject.getPrototypeOf(this).foo.call(this)

扩展运算符

//数组转对象。深刻理解iterator遍历
 let a = { ...['a', 'b', 'c'] }; // {0: "a", 1: "b", 2: "c"}

//与解构赋值结合
[a, ...rest] = [1,2,3]

数组实用方法

[1, 2, 7, 4].find((n) => n >5);  //7;返回第一个满足条件的值

[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}); // 2;返回第一个满足条件的下标

['a', 'b', 'c'].fill(7, 1, 3)  // ['a', 7, 7]

Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]

Array.of(1, 2) // [1, 2]

函数

参数作用域

一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。

//Example1
var x = 1;
function f(x, y = x) {
  console.log(y);
}
f(2) // 2

//Example2
var x = 1;
function foo(x = x) { //等价于let x = x;暂时性死区
}
foo() // ReferenceError: x is not defined

//Example3
function f(y = x) {
  let y = 2;
  console.log(y);
}
f() //Identifier 'y' has already been declared

let & const

  • 不存在变量提升
console.log(bar); // Uncaught ReferenceError: Cannot access 'bar' before initialization
let bar = 2;  
  • 暂时性死区

区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

//example1
var tmp = 123;
if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

//example2
let x2 = x2;  // ReferenceError
  • 块级作用域
// IIFE 写法
(function () {
  var tmp = ...;
  ...
}());

// 块级作用域写法
{
  let tmp = ...;
  ...
}
  • 声明变量的方式

var、function、let、const、import、class

  • 顶层对象的属性
浏览器:window(this 、 self)
Node:global

更多技术分享,欢迎【扫码关注】~
1584413667(1).jpg


夜暮sky
97 声望5 粉丝