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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。