JS prototype 原型链对象详解

一:对象的分类

  • JS中对象分为两种,函数对象普通对象。也称为Function Object和Object。通过typeof 可以查看具体的对象类型。
  • JS中的函数对象,在和new结合的时候,可以创建新的对象。JS提供了两个最基本的函数对象 FunctionObject。其他所有的对象都由这两个函数对象演进而来
  • JS中的函数对象,有两个方法可以创建,一个是通过new Function(),一个是通过function() {}声明。
  • JS中的普通对象,也有两个方法可以创建,一个是通过 new (非Function函数对象/**Object**) ,一个是通过 { }等各类语法声明。Array也可视为一个普通对象,可以通过new Array(),也可以通过[]
  • 另外,还有一个特殊的Object.create()方法,可以由一个普通对象创建一个新的普通对象。此时第一个普通对象起到类似函数对象的作用,不同之处在于,新建对象的__proto__指向第二个普通对象自身。因为普通函数没有prototype属性(这个可以看完下面的回头再理解下)。

 

var o1 = {}; 
var o2 =new Object();
var o3 = new f1();
var o4 = Object.create(o2)

function f1(){}; 
var f2 = function(){};
var f3 = new Function('str','console.log(str)');

console.log(typeof Object); //function 
console.log(typeof Function); //function  

console.log(typeof f1); //function 
console.log(typeof f2); //function 
console.log(typeof f3); //function   

console.log(typeof o1); //object 
console.log(typeof o2); //object 
console.log(typeof o3); //object
console.log(typeof o4); //object

二:prototype 和 __proto__

  • JS中的任意一个对象都包括一个 __proto__属性。该属性在ES2015之前,并没有在标准中明确定义,而是一个大多数浏览器默认支持的一个属性,也称为[[prototype]]
  • JS中的任意一个函数对象都包括了一个prototype属性。该属性相当于是当前函数对象的一个特殊实例。一般为普通对象。
  • JS中任意一个对象的__proto__属性,根据new的特性,都指向创建该对象的函数对象的prototype属性。即

 

(普通对象).__proto__ == (创建它的函数对象).prototype
(函数对象).__proto__ == Function.prototype  // 函数对象都由 new Function()创建

FunctionObject都是函数对象,都是通过new Function()创建,所以

 

Function.__proto__ == Function.prototype
Object.__proto__ == Function.prototype
  • JS中的函数对象的prototype一般都为普通对象即

 

typeof A.prototype == 'Object'  // A

Function除外,因为Function的新建实例还是一个函数对象,所以

 

typeof Function.prototype == 'function'

但是该prototype是一个特殊的函数对象。它没有prototype,另外,它的__proto__指向了Object.prototype,而不是Function的prototype,即

 

typeof Function.prototype == 'function'
Function.prototype.__proto__ == Object.prototype
  • JS中的所有函数对象的prototype都有一个constructor函数,称为构建函数,该构建函数指向当前函数对象。即

 

function f1() {}
f1.prototype.constructor == f1
Function.prototype.constructor == Function
  • prototype,__proto__以及constructor的关系图

     

    JS prototype 原型链对象详解_第1张图片

    image.png

     

    其中的person1.constructor其实是通过原型链继承在Person.prototype中寻得。

三:原型链继承

JS中的原生继承是通过原型链完成的。以下面的代码为例子

 

var Person = function(name){
  this.name = name; 
};
Person.prototype.getName = function(){
  return this.name;  // tip: 当函数执行时这个 this 指的是谁?
}
var person1 = new person('Mick');
person1.getName(); //Mick
person1.name; //Mick
person1.toString(); // [object Object]
  • 当person1执行getName方法的时候,先在person1的自身属性中寻找。此时自有属性只有name属性,未找到,则继续在person1的__proto__属性中寻找
  • 因为person1.__proto__ = Person.prototype。此时在Person.prototype中寻找getName属性,此时寻找得到,将Person.prototype.getName返回作为person1.getName,进行执行。
  • 当person1执行toString方法的时候,在Person.prototype中未能找到,则继续在Person.prototype.__proto__中寻找。
  • Person.prototype作为Person的一个特殊实例,它是普通对象。普通对象都由new Object创建。因此Person.prototype.__proto__ = Object.prototype。因此继续在Object.prototype中寻找,发现了toString方法,将Object.prototype.toString返回作为person1.toString,进行执行。
  • 需要注意,JS中的原型链继承,指的是新建对象和创建函数对象的prototype之间的关系,而不是和创建函数的关系。能够在原型链继承上传递下去的只有原型对象prototype上的函数。比如Object拥有geOwnPropertyNames方法,但Object.prototype却不包含,所以person1也无法拥有getOwnPropertyNames 方法。同样的,如果新建一个函数对象Student,让它继承Person函数对象,那么new Stuednet()新建的对象也只能继承Person.prototype.getName,而不能继承person.name属性

四:JS中原型链继承链路

  • Function函数对象

 

Function.__proto__ == Function.prototype
Function.prototype.__proto__ == Object.prototype
Object.prototype.__proto__ == null
  • Object函数对象

 

Object.__proto__ == Function.prototype
Function.prototype.__proto__ == Object.prototype
Object.prototype.__proto__ == null
  • 自定义函数对象

 

function f1() {}
f1.__proto__ == Function.prototype
Function.prototype.__proto__ == Object.prototype
Object.prototype.__proto__ == null
  • 自定义函数对象实例--也是普通对象

 

function f1() {}
o1 = new f1()
o1.__proto__ = f1.prototype
f1.prototype__proto__ == Object.prototype
Object.prototype.__proto__ == null
  • 自定义函数对象继承--继承自某一个自定义对象

 

function f1() {}
function f2() {} // 设定f2继承自f1,具体如何实现继承,可以查看另一篇文章
o2 = new f2()
o2.__proto__ = f2.prototype
f2.prototype.__proto__ = f1.prototype
f1.prototype__proto__ == Object.prototype
Object.prototype.__proto__ == null

五:总结

  • 所有的普通对象,都会继承(1)创建它的函数对象的prototype上的属性(2)函数对象继承自其它函数对象prototype上的属性(3)Object函数对象的prototype上的属性
  • 所有的函数对象,都会继承(1)Function.prototype上的属性(2)Object函数对象的prototype上的属性
  • 最后所有的对象的原型链都会追溯到null标识符上

六:Function和Object自带属性



作者:安静的牛蛙
链接:https://www.jianshu.com/p/661ca3f44b08
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(JS,javascript)