JAVAScript 原型与原型链

92 阅读3分钟

原型

(1)  显式原型 prototype:每个函数function都有一个prototype,即显式原型(属性);指向原型对象.

// prototype是函数才会有的属性

(2)  隐式原型_proto_:每个实例对象都有一个_proto_,称为隐式原型(属性);事实上就是原型链指针

(3)   对象的隐式原型属性的值=对应构造函数的显示原型属性的值;

实例._proto_=func.prototype

(4)constructor: 每一个原型对象都包含一个指向构造函数的指针,就是constructor。

原型对象中有一个constructor属性,指向函数对象(本身);

function Fun{};
//默认指向一个空的Object对象
console.log(Fun.prototype); //
console.log(Fun.prototype.constructor === Fun) //true

总结:

  • 函数的prototype:是定义函数时自动添加的,默认是一个空的Object对象;
  • 实例对象的_proto_属性:创建对象的时候自动添加的,默认为构造函数的prototype属性值。

例:

function Fun{};
//默认指向一个空的Object对象
console.log(Fun.prototype); //对应(1)

var fn = new Fun();
console.log(fn._proto) //对应(2)

console.log(fn._proto==Fun.prototype) //true   对应(3)

原型链:用来查找对象属性或者方法。

访问一个对象的属性时:

  1. 先在自身属性中查找,找到返回。

  2. 若没有,则沿着_proto_这条链向上查找,找到返回。

  3. 若最终查找到Object.prototype都没有找到, 返回undefined。

继承实现方式:

为了实现继承,proto会指向上一层的原型对象,而上一层的结构依然类似,那么就利用proto一直指向Object的原型对象上!Object.prototype.__proto__ = null;表示到达最顶端。如此形成了原型链继承。

原型链

1、Object是作为众多new出来的实例的基类 function Object(){ [ native code ] }

2、原型对象的proto都指向Object.prototype。

3、Object.prototype._proto_指向null ,也就是说Object的原型对象是原型链的尽头。

console.log(Object.prototype._proto_ === null); //true

4、所有函数都是Function的实例(包括Function)

console.log(Function._proto_ === Function.prototype); //true

5、函数的显示原型prototype指向的默认是空的Object对象(但Object不满足)

var fn = new Function(){};
console.log(fn.prototype instanceof Object); //true;
console.log(Object.prototype instanceof Object); //false;
console.log(Function.prototype instanceof Object); //true;

原型链上属性问题

1、读取对象的属性值:会自动到原型链上查找;

2、设置对象的属性值时:不会查找原型链,若当前对象没有这个属性,则直接添加这个属性并设置其值。

3、方法一般定义在原型中,属性一般通过构造函数定义在对象本身。

function Fn(name, age) {
    this.name = name;
    this.age = age;
}
fn.prototype.sex = "女"; //属性一般不定义在原型对象上, 因为每个实例的属性值不一样
fn.prototype.getName = function(){};

var fn1 = new Fn("fn1", 18);
console.log(fn1.sex); //女 ,原因是fn1对象上没有, 查找原型链中的属性返回

var fn2 = new Fn("fn2", 18);
fn2.sex = "男";

console.log(fn1.sex); //女   还是读取的原型链上的属性
console.log(fn2.sex); //男, fn2发现没有sex属性,就创建了一个sex属性, 并没有改变原型对象上的sex属性


instanceof如何进行判断的?

A instanceof B

A:实例对象
B: 构造函数

原理:

看右边的变量.prototype是否在左边变量的原型链上即可。

1、 如果B函数的显式原型对象(prototype)在A对象的原型链上,返回true, 否则返回false

2、Function是通过new自己产生的实例。

实现:

function instanceOf(left, right){
    let proto = left._proto_;
    while(proto ){
        if(proto===right.prototype){
            return true;
        } 
         proto = proto._proto_;
    }
    return false;
}

例:

function Foo(){  
}
var f1 = new Foo();
console.log(f1 instanceof Foo); //true
console.log(f1 instanof Object); //true




console.log(Object instanceof Function);//true;
console.log(Object instanceof Object); //true
console.log(Function instanceof Function); //true
console.log(Function instanceof Object); // true

console.log(Object instanceof Foo); //false

参考文章:

JavaScript深入之从原型到原型链

图解原型和原型链

www.mollypages.org/tutorials/j…