原型与原型链

原型?

    在javascript中,每当定义一个对象(函数也是对象)时,对象中都会包含一些预定义的属性。其中当定义一个函数对象时,会生成prototype原型对象属性,这个属性指向函数的原型对象。原型对象中包含着所有实例共享的属性和方法,该原型对象有两个属性:__proto__和constructor。

  每个对象实例都会在其内部初始化一个__proto__属性,他是一个指向prototype(原型对象)的指针,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,就会通过__proto__去prototype里找这个属性,这个prototype又有自己的__proto__指向自己的原型对象,于是就一直找下去,形成了原型链的概念。

   

原型链是什么?

JavaScript万物都是对象,对象和对象之间也有关系,并不是孤立存在的。对象之间的继承关系,在JavaScript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,专业术语称之为原型链。

Object的原型对象是什么???

  函数的原型对象constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针_proto_,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用_proto_一直指向Object的原型对象上,而Object的原型对象用Object.prototype._proto_ = null表示原型链的最顶端,如此便形成了javascript的原型链继承,同时也解释了为什么所有的javascript对象都具有Object的基本方法。

怎么判断一个属性是对象上的属性还是其原型对象上的属性?

obj.hasOwnProperty(attribute);

function fun(){}
//因为fun()是Function的实例
fun.__proto__==Function.prototype;//true
Function.prototype.__proto__==Object.prototype;//true;
Object.prototype.__proto__==null//true
function Person(){}
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true

使用new操作符实例化的过程
function Person(){}

// var person = new Person(); 
// 上一行代码等同于以下过程 ==> 
var person = {};
person.__proto__ = Person.prototype;
Person.call(person);

假如我们让原型对象等于另一个类型的实例,结果会怎样的?显然,此时的原型对象将包含一个指向另一个函数原型的指针。(类似于实例化一个对象的过程)

son.prototype=new parent();
等价于:
var son.prototype={};
son.prototype.__proto__=parent.prototype;
parent.call(son.prototype);

原型关系图:

 

原型链查找属性的顺序:__proto__

(1)首先在对象自身查找是否有该属性,如果有,返回结果;

(2)如果没有,就去对象的原型上进行查找,如果有,返回结果;

(3)如果没有,就沿着原型链继续往上查找,直到Object.prototype原型上,如果有,返回结果;

(4)如果Object.prototype原型上也没有,返回undefined

 constructor属性也是对象才拥有的,它是从一个对象指向一个函数。即指向该对象的构造函数。

  对于f1.constructor==Foo是因为f1对象本身不具有constructor属性,所以会通过__proto__属性向原型链中找,而f1.__proto==Foo.prototype,Foo.prototype具有constructor属性并且指向Foo函数,所以f1.constructor指向了Foo,它不是f1自身对象拥有的,是继承来的。

作用域链和原型链的区别

作用域链是针对变量的,比如我们创建一个函数,函数中又包含一个函数,此时就有三个作用域:全局作用域——函数1作用域——函数2作用域。

原型链是针对构造函数的,一般用于继承。

原文地址:https://www.cnblogs.com/xiaoan0705/p/8807577.html