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自带的函数对象。上面譬喻表达

1.介绍

 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();

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 

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()创立的。

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__属性。

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

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

function DOG(name){

this.name = name;

this.species = '犬科';

}

然后,生成多少个实例对象:

var dogA = new DOG('大毛');

var dogB = new DOG('二毛');

那五个对象的species属性是单独的,修改在那之中一个,不会耳闻则诵到另一个。

dogA.species = '猫科';

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

每多个实例对象,都有投机的质量和议程的别本。那不仅仅不可能实现数量分享,也是天崩地塌的能源浪费。

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

布伦达n Eich决定为构造函数设置贰个prototype属性。那脾个性满含叁个目的,全数实例对象急需分享的性情和章程,都投身这几个目的里面;那叁个无需分享的属性和艺术,就投身构造函数里面。实例对象一旦创设,将自动援引prototype对象的性质和方式。也正是说,实例对象的习性和方法,分成二种,一种是本地的,另一种是援用的。

  所以,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

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

   从这么些事例能够观望,通过给person.prototype设置了多少个函数对象的习性,那有person实例(例中:zjh)出来的平时对象就一连了那些天性。具体是怎么落到实处的继续,就要讲到下边包车型大巴原型链了。

DOG.prototype.species = '猫科';

alert(dogA.species); // 猫科

alert(dogB.species); // 猫科

三.原型链

由于具备的实例对象分享同四个prototype对象,那么从外侧看起来,prototype对象就恍如是实例对象的原型,而实例对象则类似"承接"了prototype对象同样。

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

2.3原型prototype

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

在JavaScript 中,每当定义三个目的(函数)时候,对象中都会含有部分预订义的习性。此中函数对象的贰本品质正是原型对象 prototype。普通对象没有prototype,但有__proto__属性。

同样,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

2.4 原型链

接轨,Object.prototype对象也许有__proto__属性,但它比较特殊,为null

JS在创设对象(不论是日常对象依旧函数对象)的时候,都有三个称作__proto__的放到属性,用于指向创建它的函数对象的原型对象prototype。

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

本文由杏彩发布,转载请注明来源

关键词: