成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

理解Javascript的原型和原型鏈

開發(fā) 前端
結(jié)合實(shí)例闡述了原型和原型鏈的概念并總結(jié)了幾種創(chuàng)建對象的方法,擴(kuò)展原型鏈的方法。

[[315622]]

前言

總括: 結(jié)合實(shí)例闡述了原型和原型鏈的概念并總結(jié)了幾種創(chuàng)建對象的方法,擴(kuò)展原型鏈的方法。  

正文

原型

Javascript中有一句話,叫一切皆是對象,當(dāng)然這句話也不嚴(yán)謹(jǐn),比如null和undefined就不是對象,除了這倆完全可以說Javascript一切皆是對象。而Javascript對象都有一個叫做原型的公共屬性,屬性名是_proto_。這個原型屬性是對另一個對象的引用,通過這個原型屬性我們就可以訪問另一個對象所有的屬性和方法。比如: 

  1. let numArray = [1, 2, -8, 3, -4, 7]; 

Array對象就有一個原型屬性指向Array.prototype,變量numArray繼承了Array.prototype對象所有的屬性和方法。

這就是為什么可以直接調(diào)用像sort()這種方法: 

  1. console.log(numArray.sort()); // -> [-4, -8, 1, 2, 3, 7] 

也就是說: 

  1. numArray.__proto__ === Array.prototype // true 

對于其他對象(函數(shù))也是一樣(比如Date(),Function(), String(),Number()等);

當(dāng)一個構(gòu)造函數(shù)被創(chuàng)建后,實(shí)例對象會繼承構(gòu)造函數(shù)的原型屬性,這是構(gòu)造函數(shù)的一個非常重要的特性。在Javascript中使用new關(guān)鍵字來對構(gòu)造函數(shù)進(jìn)行實(shí)例化??聪旅娴睦樱?nbsp;

  1. const Car = function(color, model, dateManufactured) {  
  2.   this.color = color;  
  3.   this.model = model;  
  4.   this.dateManufactured = dateManufactured;  
  5. };  
  6. Car.prototype.getColor = function() {  
  7.     return this.color;  
  8. };  
  9. Car.prototype.getModel = function() {  
  10.     return this.model;  
  11. };  
  12. Car.prototype.carDate = function() {  
  13.     return `This ${this.model} was manufactured in the year ${this.dateManufactured}`  
  14.  
  15. let firstCar = new Car('red', 'Ferrari', '1985');  
  16. console.log(firstCar);  
  17. console.log(firstCar.carDate()); 

上面的例子中,方法getColor,carDate,getModel都是對象(函數(shù))Car的方法,而Car的實(shí)例對象firstCar可以繼承Car原型上的一切方法和屬性。

結(jié)論:每一個實(shí)例對象都有一個私有屬性_proto_,指向它的構(gòu)造函數(shù)的原型對象(prototype)。

原型鏈

在Javascript中如果訪問一個對象本身不存在的屬性或是方法,就首先在它的原型對象上去尋找,如果原型對象上也不存在,就繼續(xù)在原型對象的原型對象上去尋找,直到找到為止。那么原型對象有盡頭么?所有對象的原型盡頭是Object.prototype,那么Object.prototype這個對象的_proto_指向啥呢?答案是null。我們?nèi)粘i_發(fā)中用到的絕大多數(shù)對象的_proto_基本不會直接指向Object.prototype,基本都是指向另一個對象。比如所有的函數(shù)的_proto_都會指向Function.prototype,所有數(shù)組的_proto_都會指向Array.prototype。 

  1. let protoRabbit = {  
  2.   color: 'grey',  
  3.   speak(line) {  
  4.         console.log(`The ${this.type} rabbit says ${line}`);  
  5.   }  
  6. };  
  7. let killerRabbit = Object.create(protoRabbit);  
  8. killerRabbit.type = "assassin" 
  9. killerRabbit.speak("SKREEEE!"); 

上面代碼中變量protoRabbit設(shè)置為所有兔子對象的公有屬性對象集,killerRabbit這只兔子通過Object.create方法繼承了protoRabbit的所有屬性和方法,然后給killerRabbit賦值了一個type屬性,再看下面的代碼: 

  1. let mainObject = {  
  2.     bar: 2  
  3. };  
  4. // create an object linked to `anotherObject`  
  5. let myObject = Object.create( mainObject );  
  6. for (let k in myObject) {  
  7.   console.log("found: " + k);  
  8.  
  9. // found: bar  
  10. ("bar" in myObject);  

如上變量myObject本身并沒有bar屬性,但這里會循著原型鏈一層一層往上找,直到找到或者原型鏈結(jié)束為止。如果到原型鏈盡頭還是沒找到該屬性,那么訪問該屬性的時候就會返回undefined了。

使用for...in關(guān)鍵字對對象進(jìn)行迭代的過程,和上面訪問某個屬性循著原型鏈查找類似,會去遍歷所有原型鏈上的屬性(不論屬性是否可枚舉)。 

  1. let protoRabbit = {  
  2.   color: 'grey',  
  3.   speak(line) {  
  4.       console.log(`The ${this.type} rabbit says ${line}`);  
  5.   }  
  6. };  
  7. let killerRabbit = Object.create(protoRabbit);  
  8. killerRabbit.type = "assassin" 
  9. killerRabbit.speak("SKREEEE!"); 

上面的代碼中訪問speak的效率很高,但如果我們想創(chuàng)建很多個Rabbit對象,就必須要重復(fù)寫很多代碼。而這正是原型和構(gòu)造函數(shù)的真正用武之地。 

  1. let protoRabbit = function(color, word, type) {  
  2.   this.color = color;  
  3.   this.word = word;  
  4.   this.type = type;  
  5. }; 
  6.  protoRabbit.prototype.getColor = function() {  
  7.     return this.color; 
  8.  
  9. protoRabbit.prototype.speak = function() {  
  10.     console.log(`The ${this.type} rabbit says ${this.word}`);  
  11.  
  12. let killerRabbit = new protoRabbit('grey', 'SKREEEEE!', 'assassin');  
  13. killerRabbit.speak(); 

如上代碼,使用構(gòu)造函數(shù)的方式就可以節(jié)省很多的代碼。

結(jié)論:每一個實(shí)例對象都有一個私有屬性_proto_,指向它的構(gòu)造函數(shù)的原型對象(prototype)。原型對象也有自己的_proto_,層層向上直到一個對象的原型對象為null。這一層層原型就是原型鏈。

附贈一張原型鏈的圖:

創(chuàng)建對象的四種方法

  • 字面量對象

這是比較常用的一種方式: 

  1. let obj = {}; 
  • 構(gòu)造函數(shù)創(chuàng)建

構(gòu)造函數(shù)創(chuàng)建的方式更多用來在Javascript中實(shí)現(xiàn)繼承,多態(tài),封裝等特性。 

  1. function Animal(name) {  
  2.     this.name = name;  
  3.  
  4. let cat = new Animal('Tom'); 
  • class創(chuàng)建

class關(guān)鍵字是ES6新引入的一個特性,它其實(shí)是基于原型和原型鏈實(shí)現(xiàn)的一個語法糖。 

  1. class Animal {  
  2.   constructor(name) {  
  3.     this.name = name;  
  4.   }  
  5.  
  6. let cat = new Animal('Tom'); 

擴(kuò)展原型鏈的四種方法

  • 構(gòu)造函數(shù)創(chuàng)建

上面例子有用到使用構(gòu)造函數(shù)創(chuàng)建對象的例子,我們再來看一個實(shí)際的例子: 

  1. function Animal(name) {  
  2.     this.name = name;  
  3.  
  4. Animal.prototype = {  
  5.     run() {  
  6.     console.log('跑步');  
  7.     }  
  8.  
  9. let cat = new Animal('Tom');  
  10. cat.__proto__ === Animal.prototype; // true  
  11. Animal.prototype.__proto__ === Object.prototype; // true 

優(yōu)點(diǎn):支持目前以及所有可想象到的瀏覽器(IE5.5都可以使用). 這種方法非??欤浅7蠘?biāo)準(zhǔn),并且充分利用JIST優(yōu)化。

缺點(diǎn):為使用此方法,這個問題中的函數(shù)必須要被初始化。另外構(gòu)造函數(shù)的初始化,可能會給生成對象帶來并不想要的方法和屬性。

  • Object.create

ECMAScript 5 中引入了一個新方法: Object.create()??梢哉{(diào)用這個方法來創(chuàng)建一個新對象。新對象的原型就是調(diào)用 create 方法時傳入的第一個參數(shù): 

  1. var a = {a: 1};   
  2. // a ---> Object.prototype ---> null  
  3. var b = Object.create(a);  
  4. b.__proto__ === a; // true 

優(yōu)點(diǎn): 支持當(dāng)前所有非微軟版本或者 IE9 以上版本的瀏覽器。允許一次性地直接設(shè)置 __proto__ 屬性,以便瀏覽器能更好地優(yōu)化對象。同時允許通過 Object.create(null) 來創(chuàng)建一個沒有原型的對象。

缺點(diǎn):不支持 IE8 以下的版本;這個慢對象初始化在使用第二個參數(shù)的時候有可能成為一個性能黑洞,因?yàn)槊總€對象的描述符屬性都有自己的描述對象。當(dāng)以對象的格式處理成百上千的對象描述的時候,可能會造成嚴(yán)重的性能問題。

  • Object.setPrototypeOf

語法: 

  1. Object.setPrototypeOf(obj, prototype) 

參數(shù):

參數(shù)名 含義
obj 要設(shè)置其原型的對象。
prototype 該對象的新原型(一個對象 或 null).

  

  1. var a = { n: 1 };  
  2. var b = { m : 2 };  
  3. Object.setPrototypeOf(a, b);  
  4. a.__proto__ === b; // true 

優(yōu)點(diǎn):支持所有現(xiàn)代瀏覽器和微軟IE9+瀏覽器。允許動態(tài)操作對象的原型,甚至能強(qiáng)制給通過 Object.create(null) 創(chuàng)建出來的沒有原型的對象添加一個原型。

缺點(diǎn):這個方式表現(xiàn)并不好,應(yīng)該被棄用;動態(tài)設(shè)置原型會干擾瀏覽器對原型的優(yōu)化;不支持 IE8 及以下的瀏覽器版本。

  • _proto_ 
  1. var a = { n: 1 };  
  2. var b = { m : 2 };  
  3. a.__proto__ = b 
  4. a.__proto__ === b; // true 

使用_proto_也可以動態(tài)設(shè)置對象的原型。

優(yōu)點(diǎn):支持所有現(xiàn)代非微軟版本以及 IE11 以上版本的瀏覽器。將 __proto__ 設(shè)置為非對象的值會靜默失敗,并不會拋出錯誤。

缺點(diǎn):應(yīng)該完全將其拋棄因?yàn)檫@個行為完全不具備性能可言;干擾瀏覽器對原型的優(yōu)化;不支持 IE10 及以下的瀏覽器版本。 

 

責(zé)任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2012-01-05 15:07:11

JavaScript

2020-10-20 08:35:34

JS基礎(chǔ)進(jìn)階

2016-05-06 14:02:18

JavaScript原型鏈

2023-08-28 07:12:54

2012-11-08 10:40:47

JavaScript原型鏈

2017-04-07 11:15:49

原型鏈原型Javascript

2022-05-26 09:20:01

JavaScript原型原型鏈

2016-06-07 14:28:39

Javascript原型

2020-09-10 07:04:30

JSJavaScript 原型鏈

2022-05-26 23:14:26

原型原型鏈JS繼承

2024-08-27 12:36:33

2017-05-05 10:31:35

JavaScriptprototype__proto__

2015-11-04 09:57:18

JavaScript原型

2022-03-29 09:15:55

Javascript函數(shù)屬性

2024-08-09 12:44:45

JavaScript原型鏈鏈條

2019-02-27 16:00:48

JS原型原型鏈對象

2016-12-27 09:10:29

JavaScript原型鏈繼承

2011-08-31 14:48:33

JavaScript

2015-06-09 10:55:58

JavaScriptinstanceof運(yùn)

2013-09-18 14:01:46

JavaScript
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲国产一区在线 | 国产视频一视频二 | 欧美一区二区三区久久精品视 | 成人精品在线视频 | h漫在线观看 | 久久亚洲欧美日韩精品专区 | 在线观看精品视频网站 | 国产伦精品一区二区三区精品视频 | 国产精品精品视频一区二区三区 | 亚洲国产精品久久久 | 狠狠久| 成人教育av| 一区在线视频 | caoporn免费 | 国产高清精品在线 | 亚洲国产黄色av | 青青草视频免费观看 | 欧美一区二区三 | 婷婷综合在线 | 在线一区视频 | 亚洲精品自在在线观看 | 天天干天天色 | 国产天天操 | 国产精品一区二区av | 国产精品日韩在线观看一区二区 | 国产成人免费视频网站视频社区 | 欧美日韩专区 | 蜜桃视频麻豆 | 国产精品自拍视频网站 | 亚洲欧美激情网 | 欧日韩在线| 91中文在线观看 | 亚洲一区二区电影在线观看 | 国产精品福利网站 | 免费一级黄色 | www.玖玖玖 | 美女操网站 | 国产成人综合一区二区三区 | 日韩一区不卡 | 一区在线视频 | 91在线成人 |