似懂非懂的原型链

####概念

原型是一个对象,通过原型可以实现对象的属性继承。 js的对象中都包含一个[[Prototype]]属性,这个属性对应的就是该对象的原型。可以通过Object.getPrototypeOf(object) 来访问,浏览器中可以通过__proto__ 来访问。

  • 所有对象有”[[prototype]]”属性,浏览器中通过__proto__ 访问,非标准。这个属性指向该对象的原型对象

    作用:构成原型链,同样用于实现基于原型的继承。

    1
    2
    var obj = {}
    这种叫做字面量对象,所有的字面量对象都是通过Object()构造出来的,所以obj的__proto__属性都指向Object.prototype
  • 函数对象有”prototype”属性,这个是函数特有的属性。当一个函数被用作构造函数来创建实例时,该函数的prototype属性值将被赋值给该函数创建的对象的__proto__ 属性。即构造函数.prototype === 实例.__proto__

    作用:用来实现基于原型的继承与属性的共享。

    1
    注:Object,Function,Array,Date,Number,String,Boolean都是通过new Function()创建的,是Function的实例。
  • 原型对象有”constructor”属性,指向构造函数

举例

1
2
3
4
5
6
7
8
function Person(name, age){
this.name = name
this.age = age
this.getInfo = function(){
console.log(this.name + " " + this.age)
}
}
var richMan = new Person("tom", 18)
  • 实例对象richMan的原型是”Person{}”对象:

    richMan.__proto__ or Object.getPrototypeOf(richMan)

    在js原型对象中,包含一个”constructor”属性

    • 在 js中所有对象的__proto__属性等于其构造函数的 prototype 属性

      obj.__proto__===constructor.prototype===Object.getPrototypeof(obj)

    • 构造函数的 prototype 属性默认包括一个名为 constructor 属性 而该属性值又等于该构造函数

      Person.prototype.constructor === Person

  • 查看对象Object的原型:richMan实例对象的原型是”Person{}”对象,原型的原型是”Object”对象

    1
    2
    3
    4
    5
    6
    richMan.__proto__.__proto__ === Person.prototype.__proto__ === Object.prototype
    ----------
    console.log(typeof Object); //function Object对象本身是一个函数对象。对象的构造函数!
    Object.prototype // Object的原型就是"Object{}"对象
    Object.prototype.constructor === Object
    Object.prototype.__proto__ === null // "Object{}"对象的原型是null,是原型链的终点
  • 查看对象Function的原型:Person是一个构造函数,

    1
    2
    3
    4
    5
    Person.__proto__ === Function.prototype
    #所有函数(包括Function, Object)的原型(`__proto__`)都是Function.prototype
    Function.prototype.constructor === Function
    Function.prototype.__proto__ // Object{}对象

查找属性
1
2
通过作用域链查找标识符
通过原型链查找属性

当查找一个对象的属性时,js会向上遍历原型链,当查找到原型链的顶部(Object.prototype)也没找到指定的属性,就会返回undefined。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.MaxNumber = 9999;
Person.__proto__.MinNumber = -9999;
var will = new Person("Will", 28);
console.log(will.MaxNumber);
// 9999
console.log(will.MinNumber);
// undefined
  • Person.prototype添加了MaxNumber属性,相当于在will的原型(__proto__)上设置了该属性,在will对象上找不到,会顺着原型链继续查找到。

  • Person.__proto__ 上添加了MinNumber属性,相当于在Function.prototype上添加了该属性,与will实例毫无关联。

    1
    2
    3
    由于Function.prototype.__proto__ 指向Object.prototype,而Person制造函数的原型的原型就是他,所以可以改写成
    Person.__proto__.__proto__.MinNumber = -99999
    console.log(will.MinNumber) //-99999
hasOwnProperty()

该方法能判断一个对象是否包含自定义属性,而不是原型链上的属性