JS原型链和做客对象原型的不二法门,原型对象和原型链

JS要旨种类:浅谈 原型对象和原型链

2016/03/01 · JavaScript
· 2 评论 ·
原型对象,
原型链

初稿出处: 一像素   

在Javascript中,万物皆对象,但目的也有分别,差不离可以分成两类,即:普通对象(Object)和函数对象(Function)。

诚如而言,通过new Function发生的对象是函数对象,其他对象都是常常对象。

举例表明:

function f1(){ //todo } var f2 = function(){ //todo }; var f3 = new
Function(‘x’,’console.log(x)’); var o1 = {}; var o2 = new Object(); var
o3 = new f1(); console.log( typeof f1,//function typeof f2,//function
typeof f3,//function typeof o1,//object typeof o2,//object typeof o3
//object ); >> function function function object object object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function f1(){
    //todo
}
var f2 = function(){
    //todo
};
var f3 = new Function(‘x’,’console.log(x)’);
 
var o1 = {};
var o2 = new Object();
var o3 = new f1();
 
console.log(
    typeof f1,//function
    typeof f2,//function
    typeof f3,//function
    typeof o1,//object
    typeof o2,//object
    typeof o3 //object
);
>> function function function object object object

f1属于函数的宣示,最广大的函数定义方式,f2实际是一个匿名函数,把那么些匿名函数赋值给了f2,属于函数表明式,f3不普遍,但也是一种函数对象。

Function是JS自带的靶子,f1,f2在开立的时候,JS会自动通过new
Function()的措施来构建这几个目的,由此,那七个对象都是经过new
Function()创制的。

在Javascript中创设对象有二种艺术:对象字面量和利用new表达式,o1和o2的创造恰好对应了那二种方法,重点讲一下o3,
要是用Java和C#的笔触来了然的话,o3是f1的实例对象,o3和f1是千篇一律类型,至少自己往日这么认为,其实不然…

那么怎么知道啊? 很粗略,看o3是还是不是因而new Function发生的,
分明不是,既然不是函数对象,这就是日常对象 。

通过对函数对象和常常对象的简约明了之后,大家再来领悟一下Javascript中的原型和原型链:

在JS中,每当创制一个函数对象f1
时,该目的中都会安置一些性能,其中包涵prototype和__proto__,
 prototype即原型对象,它记录着f1的一些性能和章程。

内需小心的是,prototype
对f1是不可知的,也就是说,f1不会招来prototype中的属性和方法。

function f(){} f.prototype.foo = “abc”; console.log(f.foo); //undefined

1
2
3
function f(){}
f.prototype.foo = "abc";
console.log(f.foo); //undefined

那就是说,prototype有如何用吗? 其实prototype的紧要性功效就是后续。
通俗一点讲,prototype中定义的特性和方法都是留住自己的“后代”用的,因而,子类完全可以访问prototype中的属性和措施。

想要知道f1是怎么着把prototype留给“后代”,大家须要掌握一下JS中的原型链,此时,JS中的
__proto__
入场了,那哥们长的很古怪,隐藏的也很深,以致于你平时见不到它,但它在平常对象和函数对象中都留存,
它的功效就是保存父类的prototype对象,JS在经过new
表明式创制一个对象的时候,日常会把父类的prototype赋值给新目的的__proto__属性,这样,就形成了一代代传承…

function f(){} f.prototype.foo = “abc”; var obj = new f();
console.log(obj.foo); //abc

1
2
3
4
function f(){}
f.prototype.foo = "abc";
var obj = new f();
console.log(obj.foo); //abc

现在我们领会,obj中__proto__保存的是f的prototype,
那么f的prototype中的__proto__中保存的是怎样吗? 看下图:

亚洲必赢官网 1

如图所示,f.prototype的__proto__中保存的是Object.prototype,Object.prototype对象中也有__proto__,而从出口结果看,Object.prototype.__proto__
是null,表示obj对象原型链的落成。如下图所示:

亚洲必赢官网 2

obj对象具备这么一个原型链未来,当obj.foo执行时,obj会先找找自身是不是有该属性,但不会寻找自己的prototype,当找不到foo时,obj就沿着原型链依次去查找…

在地点的例证中,我们在f的prototype上定义了foo属性,那时obj就会在原型链上找到那个特性并实施。

 

最终,用几句话计算一下本文中涉嫌到的要紧:

  1. 原型链的多变真正是靠__proto__
    而非prototype,当JS引擎执行对象的章程时,先物色对象自我是不是留存该办法,倘使不设有,会在原型链上查找,但不会寻找自己的prototype。
  2. 一个对象的__proto__记录着自己的原型链,决定了自我的数据类型,改变__proto__就约等于改变目的的数据类型。
  3. 函数的prototype不属于自我的原型链,它是子类创造的基本,决定了子类的数据类型,是延续子类原型链的大桥。
  4. 在原型对象上定义方法和属性的目标是为着被子类继承和选拔。

 

2 赞 17 收藏 2
评论

亚洲必赢官网 3

大家好,我是IT修真院日内瓦分院第01期学员,一枚正直纯洁善良的web程序员。

一.
屡见不鲜对象与函数对象

一.
普通对象与函数对象

今天给大家分享一下,修真院官网JS(职业)义务4,深度思考中的知识点——JS原型链和走访对象原型的章程

  JavaScript
中,万物皆对象!但目的也是有分其余。分为一般对象和函数对象,Object
,Function 是JS自带的函数对象。上边举例表达

  JavaScript
中,万物皆对象!但目标也是有分其余。分为一般对象和函数对象,Object
,Function 是JS自带的函数对象。上面举例表明

1.介绍

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

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

JavaScript 中,万物皆对象。JavaScript根据”原型链”(prototype
chain)情势,来落到实处持续。

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

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

2.涉及

 console.log(typeof Object); //function
 console.log(typeof Function); //function
 console.log(typeof o1); //object
 console.log(typeof o2); //object
 console.log(typeof o3); //object
 console.log(typeof f1); //function
 console.log(typeof f2); //function
 console.log(typeof f3); //function 

 console.log(typeof Object); //function
 console.log(typeof Function); //function
 console.log(typeof o1); //object
 console.log(typeof o2); //object
 console.log(typeof o3); //object
 console.log(typeof f1); //function
 console.log(typeof f2); //function
 console.log(typeof f3); //function 

2.1对象

 

 

JavaScript中,对象是有分其余,分为一般对象和函数对象,Object ,Function
是JS自带的函数对象,function定义方式本质上如故new Function格局。

在上边的事例中 o1 o2 o3 为平日对象,f1 f2 f3
为函数对象。怎么分歧,其实很简单,凡是通过 new
Function()
成立的目的都是函数对象,其余的都是平时对象。f1,f2,归根结蒂都是因而 new
Function()的措施举行创办的。Function Object 也都是通过 New
Function()创立的。

在地点的例证中 o1 o2 o3 为常见对象,f1 f2 f3
为函数对象。怎么不一致,其实很简短,凡是通过 new
Function()
创造的靶子都是函数对象,其他的都是寻常对象。f1,f2,归根到底都是通过 new
Function()的格局展开创办的。Function Object 也都是透过 New
Function()创立的。

function  f1(){};

var f2 = function(){};

var f3 = new Function(‘str’,’console.log(str)’);

var o3 = new f1();

var o1 = {};

var o2 =new Object();

console.log(typeof  Object);  //function

console.log(typeof  Function);  //function

console.log(typeof o1);   //object

console.log(typeof o2);   //object

console.log(typeof o3);   //object

console.log(typeof  f1);   //function

console.log(typeof  f2);   //function

console.log(typeof  f3);   //function

二.
原型对象

二.
原型对象

2.2目的继承

   在JavaScript
中,每当定义一个目的(函数)时候,对象中都会含有部分预约义的习性。其中函数对象的一个特性就是原型对象
prototype。注:普通对象没有prototype,但有__proto__属性。

   在JavaScript
中,每当定义一个对象(函数)时候,对象中都会蕴藏部分预定义的性能。其中函数对象的一个性质就是原型对象
prototype。注:普通对象没有prototype,但有__proto__属性。

布伦达(Brenda)n
Eich参考C++和Java,做了简化设计,将new命令引入JavaScript中,new前面跟对象的构造函数,用来创造对象。这样做有个毛病:不可能共享方法和特性。

  原型对象实际就是普通对象(Function.prototype除外,它是函数对象,但它很越发,他并未prototype属性(后面说道函数对象都有prototype属性))。看下面的事例:
 function f1(){};
 console.log(f1.prototype) //f1{}
 console.log(typeof f1. prototype) //Object
 console.log(typeof Function.prototype) // Function,这几个更加
 console.log(typeof Object.prototype) // Object
 console.log(typeof Function.prototype.prototype) //undefined

  原型对象实际就是常见对象(Function.prototype除外,它是函数对象,但它很特殊,他从没prototype属性(前面说道函数对象都有prototype属性))。看上边的事例:
 function f1(){};
 console.log(f1.prototype) //f1{}
 console.log(typeof f1. prototype) //Object
 console.log(typeof Function.prototype) // Function,这么些非凡
 console.log(typeof Object.prototype) // Object
 console.log(typeof Function.prototype.prototype) //undefined

譬如说,在DOG对象的构造函数中,设置一个实例对象的共有属性species。

function DOG(name){

this.name = name;

this.species = ‘犬科’;

}

然后,生成七个实例对象:

var dogA = new DOG(‘大毛’);

var dogB = new DOG(‘二毛’);

JS原型链和做客对象原型的不二法门,原型对象和原型链。那五个目标的species属性是独自的,修改其中一个,不会潜移默化到另一个。

dogA.species = ‘猫科’;

alert(dogB.species); // 显示”犬科”,不受dogA的影响

每一个实例对象,都有投机的性质和格局的副本。这不但不能成功数量共享,也是石破天惊的资源浪费。

 从那句console.log(f1.prototype) //f1 {}
的出口就结果可以看来,f1.prototype就是f1的一个实例对象。就是在f1创制的时候,制造了一个它的实例对象并赋值给它的prototype,基本进度如下:
 var temp = new f1();
 f1. prototype = temp;

 从那句console.log(f1.prototype) //f1 {}
的输出就结果可以见见,f1.prototype就是f1的一个实例对象。就是在f1创制的时候,创立了一个它的实例对象并赋值给它的prototype,基本历程如下:
 var temp = new f1();
 f1. prototype = temp;

布伦达(Brenda)n
Eich决定为构造函数设置一个prototype属性。那个特性包括一个对象,所有实例对象急需共享的属性和措施,都位居这几个目的里面;这些不必要共享的性质和方式,就位于构造函数里面。实例对象一旦成立,将机关引用prototype对象的特性和章程。也就是说,实例对象的性能和措施,分成三种,一种是本地的,另一种是援引的。

  所以,Function.prototype为何是函数对象就化解了,上文提到凡是new
Function ()暴发的靶子都是函数对象,所以temp1是函数对象。
 var temp1 = new Function ();
 Function.prototype = temp1;

  所以,Function.prototype为啥是函数对象就缓解了,上文提到凡是new
Function ()爆发的靶子都是函数对象,所以temp1是函数对象。
 var temp1 = new Function ();
 Function.prototype = temp1;

function DOG(name){

this.name = name;

}

DOG.prototype = { species : ‘犬科’ };

var dogA = new DOG(‘大毛’);

var dogB = new DOG(‘二毛’);

alert(dogA.species); // 犬科

alert(dogB.species); // 犬科

那原型对象是用来做如何的呢?主要意义是用于后续。举了例子:
  var person = function(name){
   this.name = name
  };
  person.prototype.getName = function(){
     return this.name; 
  }
  var zjh = new person(‘zhangjiahao’);
  zjh.getName(); //zhangjiahao

那原型对象是用来做什么的呢?主要职能是用未来续。举了例子:
  var person = function(name){
   this.name = name
  };
  person.prototype.getName = function(){
     return this.name; 
  }
  var zjh = new person(‘zhangjiahao’);
  zjh.getName(); //zhangjiahao

species属性放在prototype对象里,是多少个实例对象共享的。只要修改了prototype对象,就会同时影响到三个实例对象。

   从那些例子可以看到,通过给person.prototype设置了一个函数对象的特性,那有person实例(例中:zjh)出来的家常对象就继续了那些特性。具体是怎么落到实处的连续,就要讲到上面的原型链了。

   从这几个例子可以观看,通过给person.prototype设置了一个函数对象的特性,那有person实例(例中:zjh)出来的平时对象就此起彼伏了那些特性。具体是怎么落到实处的接续,就要讲到下边的原型链了。

DOG.prototype.species = ‘猫科’;

alert(dogA.species); // 猫科

alert(dogB.species); // 猫科

三.原型链

三.原型链

是因为有着的实例对象共享同一个prototype对象,那么从外边看起来,prototype对象就就像是实例对象的原型,而实例对象则接近”继承”了prototype对象一样。

   JS在创造对象(不论是惯常对象依旧函数对象)的时候,都有一个名叫__proto__的放权属性,用于指向创制它的函数对象的原型对象prototype。以地方的事例为例:

   JS在创制对象(不论是寻常对象仍然函数对象)的时候,都有一个名叫__proto__的放置属性,用于指向成立它的函数对象的原型对象prototype。以地点的例证为例:

2.3原型prototype

亚洲必赢官网 ,  console.log(zjh.__proto__ ===
person.prototype) //true

  console.log(zjh.__proto__ ===
person.prototype) //true

在JavaScript
中,每当定义一个目的(函数)时候,对象中都会含有部分预约义的性质。其中函数对象的一个属性就是原型对象
prototype。普通对象没有prototype,但有__proto__属性。

无异于,person.prototype对象也有__proto__属性,它指向创设它的函数对象(Object)的prototype

平等,person.prototype对象也有__proto__特性,它指向成立它的函数对象(Object)的prototype

示例:

function  f1(){};

console.log(f1. prototype) //f1 {}

console.log(typeof  f1. prototype) //object

console.log(typeof  Function. prototype) // function

console.log(typeof  Object. prototype) // object

console.log(typeof  Function. prototype. prototype) //undefined

  console.log(person.prototype.__proto__ ===
Object.prototype) //true

  console.log(person.prototype.__proto__ ===
Object.prototype) //true

2.4 原型链

两次三番,Object.prototype对象也有__proto__属性,但它相比较十分,为null

后续,Object.prototype对象也有__proto__性能,但它比较特殊,为null

JS在创建对象(不论是普普通通对象照旧函数对象)的时候,都有一个誉为__proto__的放到属性,用于指向成立它的函数对象的原型对象prototype。

  console.log(Object.prototype.__proto__)
//null

  console.log(Object.prototype.__proto__)
//null

var person = function(name){

this.name = name

};

person.prototype.getName = function(){

return this.name;

}

var zjh = new person(‘zhangjiahao’);

zjh.getName(); //zhangjiahao

我们把这几个有__proto__串起来的截至Object.prototype.__proto__为null的链叫做原型链。如下图:
亚洲必赢官网 4
四.内存结构图

大家把那个有__proto__串起来的直到Object.prototype.__proto__为null的链叫做原型链。如下图:
亚洲必赢官网 5
四.内存结构图

以地点的例子为例:

为了进一步无时或忘和直观的展开明白,下边大家画一下地点的内存结构图:
亚洲必赢官网 6

为了越发深刻和直观的开展理解,上边大家画一下方面的内存结构图:
亚洲必赢官网 7

console.log(zjh.__proto__ === person.prototype) //true

美术约定:
亚洲必赢官网 8

图案约定:
亚洲必赢官网 9

相同,person.prototype对象也有__proto__属性,它指向创立它的函数对象(Object)的prototype

疑问解释:
1.Object.__proto__ === Function.prototype // true
  Object是函数对象,是透过new
Function()成立,所以Object.__proto__指向Function.prototype。

疑问解释:
1.Object.__proto__ === Function.prototype // true
  Object是函数对象,是透过new
Function()创造,所以Object.__proto__指向Function.prototype。

console.log(person.prototype.__proto__ === Object.prototype)
//true

2.Function.__proto__ === Function.prototype // true
  Function 也是目的函数,也是经过new
Function()创造,所以Function.__proto__指向Function.prototype。

2.Function.__proto__ === Function.prototype // true
  Function 也是目的函数,也是通过new
Function()创设,所以Function.__proto__指向Function.prototype。

后续,Object.prototype对象也有__proto__属性,但它相比突出,为null

和谐是由友好创办的,好像不合乎逻辑,但细心考虑,现实世界也有些类似,你是怎么来的,你妈生的,你妈怎么来的,你姥姥生的,……类人猿进化来的,那类人猿从哪来,向来追溯下去……,就是无,(NULL生万物)
正如《道德经》里所说“无,名天地之始”。

团结是由自己创设的,好像不符合逻辑,但细心考虑,现实世界也有些类似,你是怎么来的,你妈生的,你妈怎么来的,你姥姥生的,……类人猿进化来的,那类人猿从哪来,一向追溯下去……,就是无,(NULL生万物)
正如《道德经》里所说“无,名天地之始”。

console.log(Object.prototype.__proto__) //null

3.Function.prototype.__proto__ === Object.prototype //true
事实上那点我也有点疑忌,不过也可以试着解释一下。
Function.prototype是个函数对象,理论上他的__proto__应当本着
Function.prototype,就是他自己,自己指向自己,没有意义。
JS一贯强调万物皆对象,函数对象也是目的,给她认个祖宗,指向Object.prototype。Object.prototype.__proto__
=== null,有限支撑原型链可以正常停止。

3.Function.prototype.__proto__ === Object.prototype //true
事实上那点我也有点可疑,不过也得以试着解释一下。
Function.prototype是个函数对象,理论上她的__proto__应该针对
Function.prototype,就是他自己,自己指向自己,没有意义。
JS一贯强调万物皆对象,函数对象也是目的,给他认个祖宗,指向Object.prototype。Object.prototype.__proto__
=== null,保障原型链可以正常截止。

大家把这几个有__proto__串起来的停止Object.prototype.__proto__为null的链叫做原型链。

五.constructor

五.constructor

2.5 constructor属性

  原型对象prototype中都有个预约义的constructor属性,用来引用它的函数对象。那是一种循环引用
  person.prototype.constructor === person //true
  Function.prototype.constructor === Function //true
  Object.prototype.constructor === Object //true

  原型对象prototype中都有个预约义的constructor属性,用来引用它的函数对象。那是一种循环引用
  person.prototype.constructor === person //true
  Function.prototype.constructor === Function //true
  Object.prototype.constructor === Object //true

prototype对象有一个constructor属性,默许指向prototype对象所在的构造函数。

宏观下方面的内存结构图:
亚洲必赢官网 10

周到下方面的内存结构图:
亚洲必赢官网 11

出于constructor属性定义在prototype对象方面,意味着可以被所有实例对象继承。

有两点必要留意:
(1)注意Object.constructor===Function;//true
本身Object就是Function函数构造出来的 
(2)如何寻找一个目标的constructor,就是在该目标的原型链上搜寻碰着的首先个constructor属性所针对的目的

有两点须要专注:
(1)注意Object.constructor===Function;//true
本身Object就是Function函数构造出来的 
(2)如何寻找一个对象的constructor,就是在该目的的原型链上追寻遇到的首先个constructor属性所针对的目标

constructor属性的功能,是识别原型对象到底属于哪个构造函数。

六.总结

六.总结

2.6 总结

1.原型和原型链是JS完毕持续的一种模型。
2.原型链的变异是真的是靠__proto__ 而非prototype

1.原型和原型链是JS达成持续的一种模型。
2.原型链的变异是真正是靠__proto__ 而非prototype

1.原型和原型链是JS完成再而三的一种模型。

要深切精晓那句话,大家再举个例证,看看前边你实在了解了吗?
  var animal = function(){};
  var dog = function(){};

要深远驾驭那句话,大家再举个例证,看看前面你实在精晓了吗?
  var animal = function(){};
  var dog = function(){};

2.原型链的演进是真正是靠__proto__ 而非prototype。

  animal.price = 2000;//
  dog.prototype = animal;
  var tidy = new dog();

  animal.price = 2000;//
  dog.prototype = animal;
  var tidy = new dog();

3.常见问题

  console.log(dog.price) //undefined
  console.log(tidy.price) // 2000

  console.log(dog.price) //undefined
  console.log(tidy.price) // 2000

走访对象原型的措施有哪些?

怎么呢?画一下内存图:
亚洲必赢官网 12

为何吗?画一下内存图:
亚洲必赢官网 13

4.缓解方法

  这注解什么问题吗,执行dog.price的时候,发现并未price那一个特性,即便prototype指向的animal有那几个特性,但它并没有去沿着这么些“链”去寻找。同样,执行tidy.price的时候,也不曾这些特性,可是__proto__本着了animal,它会沿着那几个链去探寻,animal中有price属性,所以tidy.price输出2000。由此得出,原型链的实在形成是靠的__proro__,而不是prototype。
为此,如若在那样指定dog.__proto__ = animal。那dog.price = 2000。

  那表达怎么样问题啊,执行dog.price的时候,发现没有price那几个特性,固然prototype指向的animal有其一特性,但它并不曾去沿着这么些“链”去追寻。同样,执行tidy.price的时候,也从没那么些特性,不过__proto__针对了animal,它会顺着那个链去摸索,animal中有price属性,所以tidy.price输出2000。因而得出,原型链的实在形成是靠的__proro__,而不是prototype。
据此,假诺在那样指定dog.__proto__ = animal。那dog.price = 2000。

收获实例对象obj的原型对象,有三种方法:

  1. obj.__proto__

  2. obj.constructor.prototype

  3. Object.getPrototypeOf(obj)

地点三种格局之中,前二种都不是很可相信。最新的ES6标准规定,__proto__性能唯有浏览器才需求配置,其他条件可以不配备。而obj.constructor.prototype在手动改变原型对象时,可能会失灵。

5.编码实战

6.恢弘思考

1.Object.__proto__ === Function.prototype // true

2.Function.__proto__ === Function.prototype // true

3.Function.prototype.__proto__ === Object.prototype //true

1.Object是函数对象,是通过new
Function()成立,所以Object.__proto__指向Function.prototype。

2.Function 也是目标函数,也是由此new
Function()创设,所以Function.__proto__指向Function.prototype。

3.Function.prototype是个函数对象,理论上其__proto__应当本着
Function.prototype,就是它和谐,自己指向自己,没有意思。函数对象也是目的,给它设定根指向Object.prototype,Object.prototype.__proto__
=== null,保障原型链可以健康停止。

7.参考文献

参考一:阮一峰:Javascript继承机制的统筹思想

参考二:zhangjiahao8961:JavaScript原型及原型链详解

8.更加多钻探

JavaScript 对象的接续机制

鸣谢

谢谢我们看到

PPT链接

视频链接

JS原型对象和原型链简介_腾讯视频


后天的分享就到那里呀,欢迎咱们点赞、转载、留言、拍砖~

下期预先报告:简述JS面向对象编程,不见不散~

网站地图xml地图