一、理解面向对象

二、对象创建的方式

1.new Object() 方式

const obj = new Object()
obj.name = 'cara'
obj.age = 18
console.log(obj)

2.字面量方式

const obj = {
    name: 'cara',
    age: 18
}
console.log(obj)

3.工厂模式

4.构造函数方式

5.原型方式

6.构造函数+原型方式

7.类方式

class Star {
    constructor (name, age) {
        this.name = name
        this.age = age
    }
    // 类中的方法也指向实例对象
    sing () {
        console.log(this.name)
    }
}
const ldh = new Star('刘德华', 18)
ldh.sing()

三、对象继承的方式

1.构造函数继承(call/apply)

function Animal (name) {
    this.name = "wang"
}
function Cat (name, age) {
    Animal.call(this)
    this.age = age
}
const cat = new Cat('wang', 1)
console.log(cat)

2.prototype原型链继承

3.类继承(extends+super)

class Father {
    constructor (uname) {
        this.uname = uname
    }
    // 普通函数
    sing () {
        console.log(123)
    }
    // 构造函数
    dance () {
        console.log(this.uname)
    }
}
class Son extends Father {
    constructor (uname) {
        // 调用构造函数时
        super(uname)
        this.uname = uname
    }
    // 调用普通函数时
    song () {
        super.sing()
    }
}
const son = new Son('cara')
// 儿子调用普通函数
son.song()
// 儿子调用构造函数
son.dance()

四、new的过程

使用new调用构造函数会执行如下步骤:

  1. 在内存中创建一个新对象。
  2. 这个新对象内部的[[Prototype]]指针被赋值为构造函数的 prototype 属性。
  3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。
  4. 执行构造函数内部的代码(给新对象添加属性)。
  5. 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

五、总结

最后再来个总结:

  1. JS中的函数可以作为函数使用,也可以作为类使用。
  2. 作为类使用的函数实例化时需要使用new
  3. 为了让函数具有类的功能,函数都具有prototype属性。
  4. 为了让实例化出来的对象能够访问到prototype上的属性和方法,实例对象的__proto__指向了类的prototype。所以prototype是函数的属性,不是对象的。对象拥有的是__proto__,是用来查找prototype的。
  5. prototype.constructor指向的是构造函数,也就是类函数本身。改变这个指针并不能改变构造函数。
  6. 对象本身并没有constructor属性,你访问到的是原型链上的prototype.constructor
  7. 函数本身也是对象,也具有__proto__,他指向的是JS内置对象Function的原型Function.prototype。所以你才能调用func.call,func.apply这些方法,你调用的其实是Function.prototype.callFunction.prototype.apply
  8. prototype本身也是对象,所以他也有__proto__,指向了他父级的prototype__proto__prototype的这种链式指向构成了JS的原型链。原型链的最终指向是Object的原型。Object上面原型链是null,即Object.prototype.__proto__ === null
  9. 因为JS中所有函数的原型都是Function.prototype,也就是说所有函数都是Function的实例。Function本身也是可以作为函数使用的----Function(),所以他也是Function的一个实例。类似的还有Object,Array等,他们也可以作为函数使用:Object(), Array()。所以他们本身的原型也是Function.prototype,即Object.__proto__ === Function.prototype。换句话说,这些可以new的内置对象其实都是一个类,就像我们的Puppy类一样。
  10. ES6的class其实是函数类的一种语法糖,书写起来更清晰,但原理是一样的。