JavaScript 语言精粹:原型与继承

原型链

JavaScript 原型链

JavaScript 原型链

基本上所有函数都含有 prototype 原型属性,除了 Function.prototype.bind() 方法生成的函数

1
2
3
const foo = Function.prototype.bind()
typeof foo // -> "function"
foo.prototype === undefined // -> true

new 过程

  1. 新建空对象 {}

    1
    var obj = {}
  2. 设置对象 constructor 属性为构造函数,根据引擎环境设置原型属性

    1
    obj.__proto__ = Fn.prototype
  3. 使用新对象调用函数构造器,上下文 this 被指向该对象

    1
    Fn.call(obj)
  4. 返回新对象(引用地址)。

    注意:若构造函数最终返回值类型为基本数据类型(numberstringbooleannullundefined),则 new 之后返回刚刚创建的实例对象;若构造函数返回值类型为引用类型,则返回这个引用值

Function.proto === Function.prototype

如图:

Function.prototype

解析:

  • Object.prototype 由引擎创建,不是由 Object() 函数创建。所有实例都是对象,但是对象不一定都是实例。
  • Function.prototype 也由引擎创建。首先引擎创建了 Object.prototype ,然后创建了 Function.prototype ,并且通过 __proto__ 将两者联系了起来
  • 不是所有函数都是 new Function() 产生的。有了 Function.prototype 以后才有了 function Function() ,然后其他的构造函数都是 function Function() 生成的。

Function.prototype

实现继承

ES5 写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Super() {}
Super.prototype.getNumber = function() {
return 1
}

function Sub() {}
Sub.prototype = Object.create(Super.prototype, {
constructor: {
value: Sub,
enumerable: false,
writable: true,
configurable: true
}
})

const s = new Sub()
s.getNumber() // -> 1

ES6 写法:

1
2
3
4
5
6
7
8
class SubDate extends Date {
logTime () {
console.log(`Time: ${this.getTime()}`)
}
}
const myDate = new SubDate()
myDate.getTime() // -> xxxxxxxxxxxxx
myDate.logTime() // -> Time: xxxxxxxxxxxxx

[参考资料]

晓月风尘 wechat
扫描二维码与我相识
你我共同创造价值,记得支持一下哦~