原型
原型是一个对象,每个函数对象(在 javascript 之对象中说过函数也是对象 )都有一个属性(prototype)指向这个对象 -- 原型对象,这个对象的作用是让所有对象实例共享原型对象中的属性,方法.即我们可以把公共的属性,方法写在这个原型中,所以说 js 中的继承是基于原型实现的;
构造函数,原型,实例
每个构造函数都有一个原型对象,原型对象包含一个指针指向构造函数,而实例包含一个指向原型对象的内部指针;
function Person(name,age){
this.name=name;
this.age=age;
}
console.dir(Person);
如图:
Person 有个属性 prototype 指向原型对象
原型对象通过 constructor 指向函数对象
prototype 函数才具有的属性,指向构造函数的原型对象;
JavaScript 中的对象,都有一个内置属性 [[Prototype]] (在 ES5 之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过__proto__来访问.ES5 中有了对于这个内置属性标准的 Get 方法 Object.getPrototypeOf()) _proto_ 指向创建它的函数对象的原型对象;
Object.getPrototypeOf() 可以查看MDN的介绍:https://developer.mozilla.org/zh-CN/docs/web/JavaScript/Reference/Global_Objects/Object/GetPrototypeOf
原型链
概念
原型链是一种机制,指的是 JavaScript 每一个对象,包括原型对象都有一个内部的 [[proto]] 属性,它指向创建它的函数对象的原型对象.这个属性是编程不可见的(虽然 ES6 标准中开放了这个属性,然而浏览器对这个属性的可见性的支持不同).
当一个对象需要引用一个属性时,JavaScript 引擎首先会从这个对象自身的属性表中寻找这个属性标识,如果找到则进行相应读写操作,如果没有在自身的属性表中找到,则在_proto_属性引用的对象(原型对象)的属性表中查找,如此往复,直到找到这个属性或者_proto_属性指向 null 为止(object prototype ).
对象的_proto_的引用链,称为原型链.
注意:有一个性能优化的问题:原型链越深,耗费的时间越多,同理作用域链也是这样.
作用
原型链的存在,主要是为了实现对象的继承.
涉及几个重要的概念
理解原型链,需要从几个概念入手.
1,函数对象
在 JavaScript 中,函数也是对象.
2,原型对象
当定义一个函数对象时,会包含一个内部属性,叫 prototype 称之为原型对象.
//普通对象
var a = {};
console.log(a.prototype);//undefined
3,__proto__
在创建对象的时候,都会有一个 [[proto]] 的内部属性,用于指向创建它的函数对象的 prototype(函数对象 prototype 指向函数的原型对象).原型对象也有 [[proto]] 属性,因此在不断的指向中,形成了原型链.
举个例子来说,我们将对象 F 的原型对象修改一下,就可以清楚看到上述的关系
function F(){};
var f = new F();
console.log(f.__proto__);
4,new
当使用 new 去调用构造函数时,相当于执行了
var o = {};
o.__proto__ = F.prototype;
F.call(o);
在原型链的实现上,new 起到了很关键的作用.
5,constructor
原型对象 prototype 上都有个 constructor 属性,指向它的函数对象,如上图.
在实际运用中,经常这样写:
function F(){};
F.prototype = {
constructor : F,
doSomething : function(){}
}
这里要加 constructor 是因为重写了原型对象,之前的 constructor 属性跟重写的原型对象没有任何关系,所以需要自己手动补上.
6,原型链结构
function F(){
this.name = 'zhang';
};
var f1 = new F();
var f2 = new F();
完整原型链
来源: https://www.cnblogs.com/CandyManPing/p/8335834.html