JS的原型和原型链
JS一切皆对象,类和实例是如何继承,需要通过原型和原型链的知识解答。
一、每一个对象都有2个隐藏的属性
-
对象.__proto
__它指向的是该对象的构造函数的原型属性(prototype,即原型对象)。
用来实现继承的,即该对象先在自己身上找有没有方法
//比如:数组 var arr=[]; arr.push();
上面这个例子中,
push
并不是写在arr
这个实例身上的,而是在Array构造函数中,它首先会在arr中找push方法,因为是它点出来的,但是没有,则通过它的_proto_
它的父级即Array
的原型属性中找有没有,这时是有的,如果父级也没有,则继续通过_proto_
往上找,如果找到Object
还没有,则直接报错。以上类似于作用域,这里称之为原型链 -
对象.constructor
每个实例(对象)都隐藏着一个constructor属性,该属性指向它的构造函数(也就是这个对象是由哪个母体实例化出来的)
即指向的是该对象的构造器(即它的父亲是谁,它的构造函数)
//比如任何数组的实例的构造函数都是Array var arr=[]; arr.constructor;//Array
二、每一个函数也有2个隐藏的属性
其实每一个函数都可以是一个构造函数,即都可以实例化对象。
也就是构造函数是函数,所有的实例(对象)都是构造函数实例化出来的,但函数本身也是对象。这就有点像鸡生蛋、蛋生鸡的问题。
-
函数.prototype
只要是一个函数,就会有一个
prototype
属性,实际上它也是一个对象,我们习惯上称之为原型对象。该原型对象上有2个属性:constructor
和__proto__
属性,前者指向函数本身,后者指向Function.prototype
函数的原型对象是对象,即
Function.prototype
是Object
在该原型上添加的属性和方法都可以被实例化的那个对象所调用。
举例,比如给数组的构造函数Array添加prototype就可以让构造出来的数组实例都拥有该方法。
Array.prototype.sum=function(){ //代码 } //所有的数组实例即刻拥有sum方法,如果不这么写,那需要给每一个数组都要单独写一次 var a1=new Array();
-
函数.__proto__
函数也是对象。每个函数都是Function类型创建的对象实例。
所有构造函数的
__proto__
都指向Function.prototype
,它是一个空函数例子:
// 内置构造函数 Number.__proto__ === Function.prototype // true Boolean.__proto__ === Function.prototype // true String.__proto__ === Function.prototype // true Object.__proto__ === Function.prototype // true Function.__proto__ === Function.prototype // true Array.__proto__ === Function.prototype // true RegExp.__proto__ === Function.prototype // true Error.__proto__ === Function.prototype // true Date.__proto__ === Function.prototype // true //自定义类的构造函数: function Person() {}// 函数声明 var Man = function() {}// 函数直接量 console.log(Person.__proto__ === Function.prototype) // true console.log(Man.__proto__ === Function.prototype) // true
相关单词:
- prototype 原型对象
- constructor 建设,构造器