原型链

1.创建对象的方法

// 第一种方式:字面量
var o1 = {name: 'o1'};
var o2 = new Object({name: 'o2'}); //若把Object当做构造函数,可当做第二种方式
//第二种方式:通过构造函数
var F = function(name){this.name=name;}
var o3 = new F('o3');
//第三种方式:Object.create, o4.__proto__指向m
var m = {name:'o4'};
var o4 = Object.create(m);

2.原型、构造函数、实例、原型链
原型链_第1张图片

(1)构造函数:任何函数只要被new使用了,就是构造函数,不被new使用就是普通函数。构造函数也是函数。即上述代码中的F.
(2)实例:上述代码中的o1/o2/o3, 都是实例,也是对象。
(3)函数在被声明的时候,js就会自动为它加上prototype属性,就是函数的原型对象。
(4)原型对象如何区分被哪个构造函数引用:原型对象的constructor(构造器)默认指向声明的函数。
(5)实例上的__proto__属性指向原型对象

原型链_第2张图片

(6)原型链:从实例对象往上找,构造这个实例相关联的对象,这个关联对象再往上找创造它的上一级原型对象,以此类推,一直到Object.prototype原型对象终止。Object的prototype是整个原型链的顶端。
(7)原型链上的方法和属性是被不同实例对象所共享的.

F.prototype.say = function(){console.log('Say Hi');}
var o5 = new F('o5');

原型链_第3张图片

(8)若在实例本身上找不到某属性或方法,会在该实例的原型对象上找(通过__proto__),若找不到会在该原型对象的上一级原型对象找(通过__proto__),以此类推,直到Object.prototype上若没有,则该实例的某属性或方法没有定义。如果在中间某个原型对象上找到了,则返回该原型对象的某属性或方法,停止向上查找。

总结:函数才有prototype,对象是没有prototype的。只有实例对象有__proto__。
普通函数看到有__proto__属性,是因为普通函数其实也是Function构造函数的实例对象。
关系图超级重要!!!

image.png
3.instanceof
原理:判断实例对象的__proto属性是否跟构造函数的prototype属性同一个引用,需注意:在同一个原型链上的构造函数,实例对象在调用instanceof时,都是返回true.

A继承B,B继承C,a是A的实例对象,a instanceof B 返回true, a instanceof C 返回true, a instanceof A 返回true,如果判断a是由谁直接生成的实例呢?使用a.__proto__.constructor。

原型链_第4张图片
4.new 运算符
原理步骤:
(1) 一个新的空对象被创建,它继承自构造函数F的prototype;
(2) 构造函数F被执行。执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new F等同于new F(),只能用在不传递任何参数的情况下。
(3) 如果构造函数返回了一个“对象”,那么这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那么new出来的结果为步骤1所创建的对象。

var new2 = function(func){
    var o = Object.create(func.prototype);
    var k = func.call(o);
    if(typeof k === 'object'){
        return k;
    }else{
        return o;
    }
}

原型链_第5张图片

你可能感兴趣的:(javascript)