共计 2321 个字符,预计需要花费 6 分钟才能阅读完成。
prototype
只有函数有 prototype 属性
let a = {}
let b = function () {}
console.log(a.prototype) // undefined
console.log(b.prototype) // {constructor: function(){...} }
其实 Object
是一个全局对象,也是一个构造函数,以及其余根本类型的全局对象也都是构造函数:
function outTypeName(data, type) {let typeName = Object.prototype.toString.call(data)
console.log(typeName)
}
outTypeName(Object) //[object Function]
outTypeName(String) // [object Function]
outTypeName(Number) // [object Function]
为什么只有函数有 prototype 属性
JS 通过 new
来生成对象,然而仅靠构造函数,每次生成的对象都不一样。
有时候须要在两个对象之间共享属性,因为 JS 在设计之初没有类的概念,所以 JS 应用函数的 prototype
来解决这部分 须要被共享的属性 ,通过函数的prototype
来模仿类:
当创立一个函数时,JS 会主动为函数增加 prototype
属性,值是一个有 constructor
的对象。
以下是共享属性 prototype
的栗子:
function People(name) {this.name = name}
People.prototype.age = 23 // 岁数
// 创立两个实例
let People1 = new People('OBKoro1')
let People2 = new People('扣肉')
People.prototype.age = 24 // 长大了一岁
console.log(People1.age, People2.age) // 24 24
People1
和 People2
的原型是People.prototype
原型链
__proto__
和Object.getPrototypeOf(target)
:对象的原型
__proto__
是对象实例和它的构造函数之间建设的链接,它的值是:构造函数的 `prototype。
也就是说:__proto__
的值是它所对应的原型对象,是某个函数的prototype
Object.getPrototypeOf(target)
全等于__proto__
。
它是 ES6 的规范,兼容 IE9,支流浏览器也都反对。
不要再应用__proto__
:
__proto__
属性没有写入 ES6 的注释,而是写入了附录。- 起因是它实质上是一个外部属性,而 不是一个正式的对外的 API,只是因为浏览器广泛支持,才被退出了 ES6。
- 规范明确规定,只有浏览器必须部署这个属性,其余运行环境不肯定须要部署,而且新的代码最好认为这个属性是不存在的。
- 所以无论从语义的角度,还是从兼容性的角度,都不要应用这个属性,应该应用:
Object.getPrototypeOf(target)
(读操作)、Object.setPrototypeOf(target)
(写操作)、Object.create(target)
(生成操作)代替
构造函数是什么
所谓的构造函数,实际上就是通过关键字 new
来调用的函数:
let newObj = new someFn() // 结构调用函数
原型继承就是利用结构调用函数的个性:
SubType.prototype = new SuperType(); // 原型继承:SubType 继承 SuperType
SubType.prototype.constructor = SubType // 从新指定 constructor 指向 不便找到构造函数
// 挂载 SuperType 的 this 和 prototype 的属性和办法到 SubType.prototype 上
- 结构调用的第二点:将新对象的
Object.getPrototypeOf(target)
指向函数的prototype
- 结构调用的第三点:该函数的 this 会绑定在新创建的对象上。(所以父类
this
申明的属性被所有子类实例共享) - 新对象赋值给
SubType.prototype
原型链是什么
来看个例子:
function foo() {}
const newObj = new foo() // 结构调用 foo 返回一个新对象
const newObj__proto__ = Object.getPrototypeOf(newObj) // 获取 newObj 的原型对象
newObj__proto__ === foo.prototype // true 验证 newObj 的原型指向 foo
const foo__proto__ = Object.getPrototypeOf(foo.prototype) // 获取 foo.prototype 的原型
foo__proto__ === Object.prototype // true foo.prototype 的原型是 Object.prototype
能够用以下三句话来了解原型链:
- 每个对象都领有一个原型对象 :
newObj
的原型是foo.prototype
。 - 对象的原型可能也是继承其余原型对象的 :
foo.prototype
也有它的原型Object.prototype
。 - 一层一层的,以此类推,这种关系就是原型链。
原型链的起点: Object.prototype
Object.prototype
是原型链的起点,所有对象都是从它继承了办法和属性。
Object.prototype
没有原型对象:
const proto = Object.getPrototypeOf(Object.prototype) // null
正文完
发表至: javascript
2020-12-23