从新认识javascript对象(三)——原型及原型链

1、原型检测

javascript中提供Object.getPrototypeOf()方法来得到对象的直接原型。javascript

function Person() {
    this.name = 'sillywa'
}
var person1 = new Person()
Object.getPrototypeOf(person1)  // {constructor: ƒ Person()}
Object.getPrototypeOf(person1.__proto__)  // Object.prototype

var person = {
    name: 'sillywa'
}
var person2 = Object.create(person)
Object.getPrototypeOf(person2)  // {name: "sillywa"}
复制代码

javascript有如下几种方法检测一个对象的原型:java

  1. isPrototypeOf():检测一个对象是不是另外一个对象的原型
  2. obj.constructor.prototype:检测非Object.create()建立的对象的原型
var obj1 = {
    name: 'sillywa'
}
var obj2 = Object.create(obj1)

// isPrototypeOf()方法
Object.prototype.isPrototypeOf(obj1)  // true
obj1.isPrototypeOf(obj2)  // true
Object.prototype.isPrototypeOf(obj2)  // true

// obj.constructor.prototype
obj1.constructor.prototype === Object.prototype  // true
// obj1是obj2的原型,如下等式应为true
obj2.constructor.prototype === obj1  // false
// 而实际上
obj2.constructor.prototype === Object.prototype  // true
复制代码

以上代码中obj1obj2的原型,obj2.constructor.prototype === obj1应为true可是实际上倒是false,由于obj2__proto__里面并无一个constructor属性,obj2.constructor其实是obj1__proto__里面的constructor,因此obj2.constructor.prototype === Object.prototype浏览器

1、constructor__proto__prototype之间的关系

在javascript中咱们每建立一个对象,该对象都会得到一个__proto__属性(该属性是个对象),该属性指向建立该对象的构造函数的原型prototype,同时__proto__对象有一个constructor属性指向该构造函数。这里咱们须要注意的是只有函数才有prototype,每一个对象(函数也是对象)都有__proto__Object自己是个构造函数。举例来讲:bash

var obj = new Object()
// 也可使用对象字面量建立,但使用Object.create()状况会不同
// Object自己是个构造函数
Object instanceof Function  // true
obj.__proto__ === Object.prototype  // true
obj.__proto__.constructor === Object  // true
// 咱们通常习惯这样写
obj.constructor === Object  // true
复制代码

当咱们访问obj.constructor的时候,obj自己是没有constructor属性的,但属性访问会沿着__proto__向上查找,即在obj.__proto__里面寻找constructor属性,若是找到了就返回值,若是未找到则继续向上查找直到obj.__proto__.__proto__...(__proto__) === null为止,没有找到则返回undefined。这样由__proto__构成的一条查找属性的线称为‘原型链’。函数

2、进一步探讨

咱们知道JS是单继承的,Object.prototype是原型链的顶端,全部对象从它继承了包括toString等等方法和属性。this

前面咱们说到Object自己是构造函数,那么它继承了Function.prototype;Function也是对象,继承了Object.prototype。这里就有一个鸡和蛋的问题:spa

Object instanceof Function  // true
Function instanceof Object  // true
复制代码

如下是ES规范的解释:prototype

Function自己就是函数,Function.__proto__是标准的内置对象Function.prototypeFunction.prototype.__proto__是标准的内置对象Object.prototypecode

function Person(name) {
    this.name = name
}
var person1 = new Person('sillywa')
复制代码

总的来讲:先有Object.prototype(原型链顶端),Function.prototype继承Object.prototype而产生,最后,FunctionObject和其它构造函数继承Function.prototype而产生。cdn

3、Object.create()

咱们知道经过Object.create()建立的对象实际上等于将该对象的__proto__指向Object.create()里面的参数对象,那么当涉及到原型时它是怎么工做的呢?

var a = {
    name: 'sillywa'
}
var b = Object.create(a)

b.__proto__ === Object.prototype  // false
b.__proto__ === a  // true
b.__proto__.constructor === Object  // true
b.__proto__.hasOwnProperty('constructor')  // false
复制代码

下面咱们来具体看一看当var b = Object.create(a)到底发生了什么,如下实在浏览器中的结果:

咱们能够看到当 var b = Object.create(a)其实是把 b__proto__指向了 a。当访问 b.constructor时,实际上访问的是 b.__proto__.__proto__.constructor

4、实例与总结

function Person(name) {
    this.name = name
}
var person1 = new Person('sillywa')

person1.__proto__ === Person.prototype
person1.__proto__.__proto__ === Person.prototype.__proto__
person1.__proto__.__proto__ === Object.prototype
Person.prototype.__proto__ === Object.prototype 
person1.__proto__.__proto__.__proto__ === null

Person.__proto__ === Function.prototype
复制代码

以上均返回true,前五个等式和第一部份内容相关,最后一个等式为第二部份内容,须要注意的是IE浏览器里面并无实现__proto__,为了便于理解咱们能够这样解释,可是最好不要在实际中使用

相关文章
相关标签/搜索