JS原型与原型链终极详解,JS宗旨种类

by admin on 2019年4月10日

JS大旨类别:浅谈 原型对象和原型链

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

原版的书文出处: 一像素   

JS原型与原型链终极详解,JS宗旨种类。在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

f壹属于函数的宣示,最常见的函数定义格局,f贰实际是一个匿名函数,把那么些匿名函数赋值给了f二,属于函数表明式,f叁不普遍,但也是1种函数对象。

Function是JS自带的对象,f壹,f2在开创的时候,JS会自动通过new
Function()的情势来营造那么些目的,因而,那四个指标都以由此new
Function()创制的。

在Javascript中创制对象有三种方法:对象字面量和应用new表达式,o1和o2的创制恰好对应了这二种艺术,重点讲一下o三,
假诺用Java和C#的思路来掌握的话,o3是f一的实例对象,o3和f1是壹律类别,至少笔者原先这么觉得,其实不然…

那正是说怎么明白吧? 很简短,看o三是还是不是透过new Function发生的,
鲜明不是,既然不是函数对象,那就是普通对象 。

由此对函数对象和通常对象的大致驾驭之后,大家再来掌握一下Javascript中的原型和原型链:

在JS中,每当创设2个函数对象f1时,该对象中都会停放一些属性,当中囊括prototype和__proto__,
 prototype即原型对象,它记录着f一的壹对质量和措施。

亟需小心的是,prototype
对f壹是不可知的,也正是说,f一不会招来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__中保存的是什么样吗? 看下图:

必发88 1

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

必发88 2

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

在地点的例证中,我们在f的prototype上定义了foo属性,那时obj就会在原型链上找到这些本性并履行。

 

聊到底,用几句话总括一下本文中涉及到的首要:

  1. 原型链的朝3暮四真就是靠__proto__
    而非prototype,当JS引擎执行对象的法马时,先找找对象自我是或不是留存该方法,假诺不存在,会在原型链上查找,但不会招来本人的prototype。
  2. 三个对象的__proto__记录着团结的原型链,决定了自作者的数据类型,改变__proto__就也就是改变目的的数据类型。
  3. 函数的prototype不属于笔者的原型链,它是子类成立的宗旨,决定了子类的数据类型,是接连子类原型链的桥梁。
  4. 在原型对象上定义方法和品质的目标是为着被子类继承和动用。

 

2 赞 17 收藏 2
评论

必发88 3

世家好,小编是IT修真院卡萨布兰卡分院第01期学员,一枚正直纯洁善良的web程序员。

1.
平时对象与函数对象

壹. 通常对象与函数对象

后日给大家享用一下,修真院官网JS(职业)职务四,深度考虑中的知识点——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;

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对象

 

在地方的例证中 o一 o二 o三 为平时对象,f一 f二 f三为函数对象。怎么差别,其实极粗略,凡是通过 new Function()
创立的对象都以函数对象,别的的都以见惯不惊对象。f一,f2,归根到底都以由此 new
Function()的方法展开创办的。Function Object 也都以通过 New
Function()创制的。

JavaScript中,对象是有分别的,分为一般对象和函数对象,Object ,Function
是JS自带的函数对象,function定义格局本质上也许new Function格局。

在上边的事例中 o一 o2 o三 为普通对象,f一 f贰 f3为函数对象。怎么差距,其实很简单,凡是通过 new
Function()
制造的指标都是函数对象,别的的都以平凡对象。f一,f二,归根到底都以通过 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.
原型对象

在JavaScript
中,每当定义一个指标时候,对象中都会含有部分预约义的本性。当中等学校函授数对象的一性格质便是原型对象
prototype。注:普通对象未有prototype,但有__proto__属性。

2.贰对象继承

   在JavaScript
中,每当定义三个对象(函数)时候,对象中都会蕴藏部分预约义的性情。当中等高校函授数对象的三个属性正是原型对象
prototype。注:普通对象未有prototype,但有__proto__属性。

原型对象实际便是普通对象(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

Brendan
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

从那句console.log(f一.prototype) //f一 {}
的出口就结果能够观察,f一.prototype就是f一的2个实例对象。就是在f一创造的时候,创设了2个它的实例对象并赋值给它的prototype,基本历程如下:
var temp = new f1();
f1. prototype = temp;

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

function DOG(name){

this.name = name;

this.species = ‘犬科’;

}

下一场,生成四个实例对象:

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

JS原型与原型链终极详解,JS宗旨种类。var dogB = new DOG(‘二毛’);

那三个对象的species属性是独立的,修改个中三个,不会潜移默化到另二个。

dogA.species = ‘猫科’;

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

每多少个实例对象,都有谈得来的习性和办法的副本。那不仅不只怕形成数量共享,也是翻天覆地的财富浪费。

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

之所以,Function.prototype为啥是函数对象就消除了,上文提到凡是new
Function ()发生的靶子都是函数对象,所以temp一是函数对象。
var temp1 = new Function ();
Function.prototype = temp1;

Brendan
Eich决定为构造函数设置多个prototype属性。这一个天性包蕴1个指标,全数实例对象必要共享的属性和办法,都位居那个目的里面;那个不供给共享的性质和艺术,就位于构造函数里面。实例对象壹旦创造,将活动引用prototype对象的质量和办法。也便是说,实例对象的性质和措施,分成二种,1种是本地的,另一种是引用的。

  所以,Function.prototype为啥是函数对象就一蹴而就了,上文提到凡是new
Function ()产生的指标都以函数对象,所以temp一是函数对象。
 var temp1 = new Function ();
 Function.prototype = temp1;

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

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

从这几个例子能够观看,通过给person.prototype设置了2个函数对象的习性,那有person实例出来的一般性对象就连任了那些本性。具体是怎么落到实处的接轨,就要讲到上边包车型地铁原型链了。

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

   从这几个例子能够看到,通过给person.prototype设置了二个函数对象的天性,那有person实例(例中:zjh)出来的一般对象就延续了那特性情。具体是怎么落到实处的后续,就要讲到上面包车型大巴原型链了。

三.原型链

DOG.prototype.species = ‘猫科’;

alert(dogA.species); // 猫科

alert(dogB.species); // 猫科

三.原型链

JS在成立对象(不论是不以为奇对象依旧函数对象)的时候,都有二个称作__proto__的松手属性,用于指向创造它的函数对象的原型对象prototype。以地方的例证为例:

鉴于负有的实例对象共享同一个prototype对象,那么从外侧看起来,prototype对象就象是是实例对象的原型,而实例对象则接近”继承”了prototype对象一样。

   JS在创制对象(不论是寻常对象依旧函数对象)的时候,都有二个誉为__proto__的放到属性,用于指向创制它的函数对象的原型对象prototype。以地方的例证为例:

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

2.3原型prototype

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

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

在JavaScript
中,每当定义贰个目的(函数)时候,对象中都会含有部分预约义的性能。当中等高校函授数对象的一天性质正是原型对象
prototype。普通对象未有prototype,但有__proto__属性。

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

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

示例:

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

后续,Object.prototype对象也有__proto__性格,但它相比较独特,为null

2.4 原型链

继承,Object.prototype对象也有__proto__性情,但它比较至极,为null

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

JS在创立对象(不论是常见对象依旧函数对象)的时候,都有一个称为__proto__的放置属性,用于指向创制它的函数对象的原型对象prototype。

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

大家把那几个有__必发88,proto__串起来的直到Object.prototype.__proto__为null的链叫做原型链。如下图:
必发88 4
四.内部存款和储蓄器结构图

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的链叫做原型链。如下图:
必发88 5
肆.内部存款和储蓄器结构图

为了进一步深入和直观的展开精通,下边大家画一下下面的内部存储器结构图:
必发88 6

以地点的例证为例:

为了更深刻和直观的进展驾驭,下边大家画一下下边的内部存款和储蓄器结构图:
必发88 7

绘画约定:
必发88 8

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

图案约定:
必发88 9

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

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

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

2.Function.__proto__ === Function.prototype // true
Function 也是指标函数,也是通过new
Function()成立,所以Function.__proto__指向Function.prototype。

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

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

投机是由本身创设的,好像不相符逻辑,但仔细思忖,现实世界也有个别类似,你是怎么来的,你妈生的,你妈怎么来的,你姥姥生的,……类人猿进化来的,那类人猿从哪来,平昔追溯下去……,正是无,
正如《道德经》里所说“无,名天地之始”。

延续,Object.prototype对象也有__proto__属性,但它相比尤其,为null

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

3.Function.prototype.__proto__ === Object.prototype //true
实际上那一点作者也有点疑心,可是也得以试着解释一下。
Function.prototype是个函数对象,理论上她的__proto__有道是本着
Function.prototype,正是他自个儿,自身指向本身,未有意义。
JS一直强调万物皆对象,函数对象也是目的,给她认个祖宗,指向Object.prototype。Object.prototype.__proto__
=== 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,有限支撑原型链能够正常甘休。

五.constructor

小编们把那个有__proto__串起来的截至Object.prototype.__proto__为null的链叫做原型链。

五.constructor

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

2.5 constructor属性

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

完善下方面包车型大巴内部存储器结构图:
必发88 10

prototype对象有2个constructor属性,暗中同意指向prototype对象所在的构造函数。

周密下方面包车型地铁内部存款和储蓄器结构图:
必发88 11

有两点必要留意:
小心Object.constructor===Function;//true
本人Object便是Function函数构造出来的
怎么着寻找三个对象的constructor,就是在该目的的原型链上摸索蒙受的第一个constructor属性所指向的对象

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

有两点需求专注:
(一)注意Object.constructor===Function;//true
本身Object正是Function函数构造出来的 
(二)怎么样寻找贰个对象的constructor,就是在该对象的原型链上搜索碰着的首先个constructor属性所针对的指标

六.总结

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

六.总结

一.原型和原型链是JS达成三番五次的壹种模型。
二.原型链的变异是确实是靠__proto__ 而非prototype

2.6 总结

一.原型和原型链是JS完成持续的壹种模型。
贰.原型链的变异是实在是靠__proto__ 而非prototype

要深切精通那句话,大家再举个例子,看看前边你真的通晓了啊?
var animal = function(){};
var dog = function(){};

一.原型和原型链是JS达成再三再四的一种模型。

要深远通晓这句话,大家再举个例证,看看前边你真正驾驭了吧?
  var animal = function(){};
  var dog = function(){};

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

贰.原型链的变异是当真是靠__proto__ 而非prototype。

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

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

三.大面积难题

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

为何呢?画一下内部存款和储蓄器图:
必发88 12

访问对象原型的方法有啥样?

缘何吗?画一下内部存款和储蓄器图:
必发88 13

那注解什么问题吧,执行dog.price的时候,发现并未有price那一个性子,尽管prototype指向的animal有那天性子,但它并不曾去沿着那个“链”去搜寻。同样,执行tidy.price的时候,也从不这一个天性,然而__proto__本着了animal,它会顺着那么些链去搜寻,animal中有price属性,所以tidy.price输出两千。因此得出,原型链的的确形成是靠的__proro__,而不是prototype。
就此,尽管在这么内定dog.__proto__ = animal。那dog.price = 2000。

四.消除格局

  那表明怎么着难点吗,执行dog.price的时候,发现并未有price那一个脾气,纵然prototype指向的animal有这么些天性,但它并不曾去沿着那一个“链”去追寻。同样,执行tidy.price的时候,也未有那特特性,不过__proto__本着了animal,它会沿着那几个链去追寻,animal中有price属性,所以tidy.price输出两千。由此得出,原型链的着实形成是靠的__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。

二.Function 也是指标函数,也是因而new
Function()创设,所以Function.__proto__指向Function.prototype。

三.Function.prototype是个函数对象,理论上其__proto__相应针对
Function.prototype,正是它和谐,自身指向本身,未有意思。函数对象也是指标,给它设定根指向Object.prototype,Object.prototype.__proto__
=== null,保障原型链能够健康停止。

柒.参考文献

参考一:阮1峰:Javascript继承机制的规划思想

参考二:zhangjiahao8九6一:JavaScript原型及原型链详解

8.更多切磋

JavaScript 对象的存在延续机制

鸣谢

谢谢大家看到

PPT链接

摄像链接

JS原型对象和原型链简介_腾讯录制


明天的享用就到那里呀,欢迎大家点赞、转载、留言、拍砖~

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

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图