前端让前端飞程序员

JS难点整理笔记

2018-05-15  本文已影响49人  tiancai啊呆

关于作用域及作用域链

首先我们需要知道一些基本概念。

关于闭包

关于原型及原型链

function Cat(name, color) {
    this.name = name;
    this.color = color;
}
var cat1 = new Cat('大毛', '白色');
console.log(Object.getPrototypeOf(cat1) === Cat.prototype)   //true
console.log(Object.getPrototypeOf(Cat.prototype) === Object.prototype)  //true
console.log(Object.getPrototypeOf(Cat) === Function.prototype)         //true
console.log(Object.getPrototypeOf(Function.prototype) === Object.prototype)  //true
//实例对象cat1的原型链为:Cat.prototype => Object.prototype => null
// Cat也是对象,它的原型链为: Function.prototype => Object.prototype => null

var o = {
    name: 'liming',
    age: 23
}
console.log(Object.getPrototypeOf(o) === Object.prototype)   //true
//实例对象o的原型链为: Object.prototype => null

关于继承

  1. 原型链继承
function Animal(name) {
    this.name = name || 'animal';
    this.sleep = function () {
        console.log(this.name + '正在sleeping!');
    }
}
Animal.prototype.eat = function (food) {
    console.log(this.name + '正在吃:' + food);
};

function Dog() {
    this.age = 4
    this.sayAge = function () {
        console.log('age is ' + this.age);
    }
}
Dog.prototype = new Animal( '二狗')

var dog = new Dog()
console.log(dog.age)             //4
console.log(dog.sayAge())       //age is 4
console.log(dog.name)           //二狗
console.log(dog.sleep())        //二狗正在sleeping!
console.log(dog.eat('骨头'))    //二狗正在吃:骨头
console.log(dog instanceof Dog)    //true
console.log(dog instanceof Animal)  //true
console.log(dog instanceof Object)   //true
  1. 构造函数继承
function Dog() {
    Animal.call(this, '二狗')
}
var dog = new Dog()
console.log(dog.name)    //二狗
console.log(dog.sleep())     //二狗正在sleeping!
console.log(dog instanceof Dog)     //true
console.log(dog instanceof Animal)  //false
console.log(dog instanceof Object)   //true
  1. 组合继承
function Dog() {
    Animal.call(this, '二狗')
}
Dog.prototype = new Animal()
Dog.prototype.constructor = Dog

var dog = new Dog()
console.log(dog.name)    //二狗
console.log(dog.sleep())   //二狗正在sleeping!
console.log(dog.eat('骨头'))  //二狗正在吃:骨头
console.log(dog instanceof Dog)    //true
console.log(dog instanceof Animal)  //true
console.log(dog instanceof Object)   //true

特点:组合继承避免了原型链继承和构造函数继承的缺陷,融合了他们的优点,成为最常用的继承模式。
使用原型链实现对原型属性和方法的继承,通过构造函数实现对实例属性和方法的继承。
缺点:调用两次父类构造函数,子类实例对象的原型会有父类的实例属性。

  1. 寄生式继承
var clone = Object.create(new Animal('二狗'))
clone.age = 4
clone.sayAge = function () {
    console.log('age is ' + this.age);
}
console.log(clone.age)    //4
console.log(clone.sayAge())      //age is 4
console.log(clone.name)    //二狗
console.log(clone.sleep())      //二狗正在sleeping!
console.log(clone.eat('骨头'))       //二狗正在吃:骨头
console.log(clone instanceof Animal)     //true
console.log(clone instanceof Object)     //true

特点:以一个对象为原型,创建一个新对象,然后对新对象进行增强,返回新对象。

  1. 寄生组合继承
function Dog() {
    Animal.call(this, '二狗')
    this.age = 4
    this.sayAge = function () {
        console.log('age is ' + this.age);
    }
}

var clone = Object.create(Animal.prototype)
Dog.prototype = clone
Dog.prototype.constructor = Dog
var dog = new Dog()
dog.colors.push('black')
console.log(dog.age)     //4
console.log(dog.sayAge())  //age is 4
console.log(dog.name)    //二狗
console.log(dog.sleep())    //二狗正在sleeping!
console.log(dog.eat('骨头'))    //二狗正在吃:骨头
console.log(dog instanceof Dog)    //true
console.log(dog instanceof Animal)  //true
console.log(dog instanceof Object)   //true

关于this

简单说,this就是属性或方法“当前”所在的对象,指向是可变的。

注意点:

固定this值

关于执行机制

看了网上很多资料,讲的都大同小异,我按照自己的理解整理了一下,欢迎纠错。

console.log("1")
setTimeout(function() {
  console.log("2")
  process.nextTick(function() {
    console.log("3")
  })
  new Promise(function(resolve) {
    console.log("4")
    resolve()
  }).then(function() {
    console.log("5")
  })
})
process.nextTick(function() {
  console.log("6")
})
new Promise(function(resolve) {
  console.log("7")
  resolve()
}).then(function() {
  console.log("8")
})

setTimeout(function() {
  console.log("9")
  process.nextTick(function() {
    console.log("10")
  })
  new Promise(function(resolve) {
    console.log("11")
    resolve()
  }).then(function() {
    console.log("12")
  })
})

//  1 7 6 8 2 4 3 5 9 11 10 12 
  1. 先打印1,没有问题,遇到setTimeout,setTimeout(简写为s1)会进入宏任务事件队列。
  2. process.nextTick进入微任务事件队列。
  3. 遇到promise立即执行,打印7,then函数进入微任务事件队列。
  4. 再遇到setTimeout,setTimeout(简写为s2)会进入宏任务事件队列。
  5. 执行微任务事件队列里面的任务,打印 6 和 8 (因为process.nextTick是先进入队列的,故先执行,遵守先进先出原则)。
  6. 执行宏任务事件队列里面的任务,先执行s1,在执行s2。
  7. 执行s1,打印2和4,s1里面的process.nextTick和then函数又进入微任务事件队列,然后打印3和5。
  8. 执行s2,打印9和11,s2里面的process.nextTick和then函数又进入微任务事件队列,然后打印10和12。

参考资料

上一篇 下一篇

猜你喜欢

热点阅读