2019-08-05

  • 闭包

函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,函数 B 就被称为闭包。

for ( var i=1; i<=5; i++) { // 使之输出1,2,3,4,5
    setTimeout( function timer() {
        console.log( i );
    }, i*1000 );
}
  1. 闭包
for (var i = 1; i <= 5; i++) {
     ( function (j) {
        setTimeout(function timer() {
        console.log(j);
    }, i * 1000);
  })(i)
}

2.使用setTimeout 第三个参数

for ( var i=1; i<=5; i++) { 
    setTimeout( function timer(j) {
        console.log( j );
    }, i*1000, i );
}
  1. 使用let,形成块级作用域
for ( let i=1; i<=5; i++) { 
   setTimeout( function timer() {
       console.log( i );
   }, i*1000);
}
  • 深浅拷贝

    • 浅拷贝(只拷贝一层)
    1. Object. assign({}, obj)
    2. ...展开符
    • 深拷贝
    1. JSON.parse(JSON.stringify(obj))
      局限性的:
      会忽略 undefined
      会忽略 symbol
      不能序列化函数
      不能解决循环引用的对象
      在遇到函数、 undefined 或者 symbol 的时候,该对象也不能正常的序列化,该方法会忽略掉函数和 undefined。
    2. 当所需拷贝的对象含有内置类型并且不包含函数,可以使用MessageChannel

    3.手动实现深拷贝

      const deepClone = obj => {
            let clone = Object.assign({}, obj);
            //  先递归遍历一遍,这时候已经得到了object的深拷贝
            Object.keys(clone).forEach(
                  key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) :  obj[key])
            );
            // 如果是数组,就单独处理一下
            return Array.isArray(obj) && obj.length? (clone.length = obj.length) && Array.from(clone): Array.isArray(obj) ? Array.from(obj) : clone;
      }
    
  • 原型
    __proto__指向原型
    原型的constructor属性指向构造函数,构造函数又通过prototype属性指回原型

2019-08-05_第1张图片
image.png

- Object是所有对象的爸爸,所有对象都可通过 __proto__找到它
- Function是所有函数的爸爸,所有函数都可以通过 __proto__找到它
- 函数的 prototype是一个对象
- 对象的 __proto__属性指向原型, __proto__ 将对象和原型连接起来组成了原型链

  • 原型继承和 Class 继承
    JS中不存在类,class只是语法糖,本质还是函数
  • 组合继承
 function Parent(value) {
      this.val = value;
  }
Parent.prototype.getValue = function() {
      console.log(this.val);
}

function Child(value) {
      Parent.call(this, value);
}
Child.prototype = new Parent();

该继承方式核心是在子类的构造函数中通过Parent.call(this)继承父类的属性,然后改变子类的原型为new Parent()来继承父类的函数。
这种继承方式优点在于构造函数可以传参,不会与父类属性共享,可以复用父类的函数,但是也存在一个缺点就是在继承父类函数的时候调用了父类的构造函数,导致子类的原型上多了不需要的父类属性,存在内存上的浪费。

  • 寄生组合式继承
function Parent(value) {
      this.val = value
}
Parent.prototype.getValue = function () {
      console.log(this.val)
}
function Child(value) {
      Parent.call(this, value)
}
Child.prototype = Object.create(Parent.prototype, {
costructor: {
      value: Child,
      enumerable: false,
      writable: true,
      configurable: true
}
})

以上继承实现的核心就是将父类的原型赋值给了子类,并且将构造函数设置为子类,这样既解决了无用的父类属性问题,还能正确的找到子类的构造函数。

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
接收的第一个参数是:新创建对象的原型对象
第二个参数:可选,如果没有指定则为undefined,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称,这些属性对应Object.defineProperties的第二个参数

Object.defineProperties直接在一个对象上定义新的属性或修改现有属性,并返回该对象
第一个参数:obj在其上定义或修改属性的对象
第二个参数:要定义其可枚举属性或修改的属性描述符的对象
configurable:true当且仅当该属性描述符的类型可以杯改变并且该属性可以从对应对象中删除。
enumerable: true当且仅当在枚举相应对象上的属性时该属性显现
value:与属性关联的值,可以时任何有效的JavaScript 值
writable:true当且仅当与该属性相关联的值可以用assignment operator改变时。
get: 作为该属性的 getter 函数,如果没有 getter 则为undefined函数返回值将被用作属性的值。
set 作为属性的setter函数,如果没有setter则为undefined,函数将仅接收参数赋值给该属性的新值。

  • class继承
    class 实现继承的核心在于使用extends表明继承自哪个父类,并且在子类构造函数中必须调用super,因为这段代码可以看成Parent.call(this, value)

你可能感兴趣的:(2019-08-05)