成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

理解js的原型與繼承

wthee / 2747人閱讀

摘要:相當(dāng)于在用原型繼承編寫復(fù)雜代碼前理解原型繼承模型十分重要。同時(shí),還要清楚代碼中原型鏈的長(zhǎng)度,并在必要時(shí)結(jié)束原型鏈,以避免可能存在的性能問題。

js是一門動(dòng)態(tài)語(yǔ)言,js沒有類的概念,ES6 新增了class 關(guān)鍵字,但只是語(yǔ)法糖,JavaScript 仍舊是基于原型。

至于繼承,js的繼承與java這種傳統(tǒng)的繼承不一樣.js是基于原型鏈的繼承.

在javascript里面,每個(gè)對(duì)象都有一個(gè)prototype屬性,指向它的原型對(duì)象.這個(gè)原型對(duì)象里面同時(shí)還有自己的原型,原型一環(huán)扣一環(huán),直到某個(gè)對(duì)象的原型為null,這一級(jí)一級(jí)的鏈結(jié)構(gòu)就是原型結(jié)構(gòu).

js的原型鏈繼承

繼承屬性

js屬性查找:由于js原型鏈的存在,當(dāng)查找一個(gè)對(duì)象屬性時(shí)候,不只是在對(duì)象上查找,還會(huì)沿著該js對(duì)象的原型鏈往上查找,知道找到一個(gè)匹配的屬性或者查找到原型鏈末尾.當(dāng)然如果js對(duì)象上與其原型的對(duì)象上都有同名的屬性,我們遵循該屬性的作用域就近原則(術(shù)語(yǔ)叫做"屬性遮蔽").

var Ele = function(){
    this.a = 1;
    this.b = 2;
     }
    var Obj = function(){
    this.c = 3;
    this.b = 4;
     }
     Ele.prototype = new Obj();
    var ele1 = new Ele(); 
    console.log(ele1.a);//1
    console.log(ele1.b);// 2
    console.log(ele1.c);// 3
    console.log(ele1.d);//undefined

繼承方法

在 JavaScript 里,任何函數(shù)都可以添加到對(duì)象上作為對(duì)象的屬性/方法。函數(shù)的繼承與其他的屬性繼承沒有差別,包括上面的“屬性遮蔽”(這種情況相當(dāng)于其他語(yǔ)言(java)的方法重寫)。

var student= {
    age : 20,
    name: "cp",
    sayhi : function(){
        console.log("hi");
    }
     }
     var s1 = Object.create(student); //一種創(chuàng)建對(duì)象的方法,后面會(huì)寫博客介紹.s1.prototype是student
       s1.name = "kobe";
     console.log( s1.name ); // "kobe"
     console.log( s1.age ); // 20
    console.log( s1.sayhi() ); // hi

多種方法創(chuàng)建對(duì)象及生產(chǎn)原型鏈

普通對(duì)象字面量創(chuàng)建對(duì)象

   var o = {
    a: 1
     };
     console.log(o.hasOwnProperty("a")); //true
    // o這個(gè)對(duì)象繼承了Object.prototype上面的所有屬性
         // 所以可以這樣使用 o.hasOwnProperty("a").判斷一個(gè)對(duì)象是否還有一個(gè)屬性
     // hasOwnProperty 是Object.prototype的自身屬性。
      // Object.prototype的原型為null。
// 原型鏈如下:
// o ---> Object.prototype ---> null
var a = ["yo", "whadup", "?"];
// 數(shù)組的實(shí)例對(duì)象都繼承于Array.prototype 
// (indexOf, forEach等方法都是從它繼承而來(lái)).
// 原型鏈如下:
// a ---> Array.prototype ---> Object.prototype ---> null
function f(){
  return 2;
}
    // 函數(shù)都繼承于Function.prototype
    // (call, bind等方法都是從它繼承而來(lái)):
    // f ---> Function.prototype ---> Object.prototype ---> null

- 使用構(gòu)造函數(shù)(構(gòu)造器)創(chuàng)建對(duì)象

    `function Student() {
     this.job = "讀書";
     this.tag = "年輕";
}
function BoyStudent() {
  this.sex = "boy";
}
BoyStudent.prototype = new Student();
var xiaoMing = new BoyStudent();
console.log(xiaoMing.sex); //boy
console.log(xiaoMing.tag); //年輕
// xiaoMing是生成的對(duì)象,他的自身屬性有"sex".
// 在BoyStudent被實(shí)例化時(shí),BoyStudent.[[Prototype]]指向了Student.prototype.

使用Object.create()創(chuàng)建對(duì)象,新對(duì)象的原型就是調(diào)用 create 方法時(shí)傳入的第一個(gè)參數(shù):

var a = {a: 1}; 
// a ---> Object.prototype ---> null
var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (繼承而來(lái))
var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null
var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined, 因?yàn)閐沒有繼承Object.prototype

使用 class 關(guān)鍵字

ECMAScript6 引入了一套新的關(guān)鍵字用來(lái)實(shí)現(xiàn) class。使用基于類語(yǔ)言的開發(fā)人員會(huì)對(duì)這些結(jié)構(gòu)感到熟悉,但它們是不一樣的。 JavaScript 仍然是基于原型的,這點(diǎn)一直不變。這些新的關(guān)鍵字包括 class, constructor, static, extends, 和 super.(跟java的關(guān)鍵字一樣,構(gòu)造器,靜態(tài),繼承,超類)

"use strict";
     //類 Person
     class Person(){
    constructor(name , age){
      this.name = name;
        this.age = age;
    };
    }
    // 類Girl繼承Person
      class Girl extends Person(){    
    constructor(name , age){
        super(name , age);
    }
    getinfo(){
        return this.name + "," + this.age;
    }
     }
    var girl = new Girl("kobe",20);

原型繼承的性能

在原型鏈上查找屬性比較耗時(shí),對(duì)性能有副作用,盡量避免,這在性能要求苛刻的情況下很重要。另外,訪問不存在的屬性時(shí)會(huì)遍歷整個(gè)原型鏈,浪費(fèi)資源。

遍歷對(duì)象的屬性時(shí),原型鏈上的每個(gè)可枚舉屬性都會(huì)被枚舉出來(lái)。

檢測(cè)對(duì)象的屬性是定義在自身上還是在原型鏈上,有必要使用 hasOwnProperty 方法,所有繼承自 Object.proptotype 的對(duì)象都包含這個(gè)方法,返回布爾值,是 JavaScript 中唯一一個(gè)只涉及對(duì)象自身屬性而不會(huì)遍歷原型鏈的方法。

注意:僅僅通過判斷值是否為 undefined 還不足以檢測(cè)一個(gè)屬性是否存在,一個(gè)屬性可能存在而其值恰好為 undefined。

關(guān)于原生對(duì)象的原型擴(kuò)展

理論上我們不應(yīng)該去擴(kuò)展Object.prototype,或者其他內(nèi)置對(duì)象的原型,像Array.prototype等。

我們?nèi)U(kuò)展內(nèi)置對(duì)象原型的唯一理由是引入新的 JavaScript 引擎的某些新特性,比如 Array.forEach。

理解prototype與Object.getPrototypeOf區(qū)別

function A(a){
    this.varA = a;
    }
    // 以上函數(shù) A 的定義中,既然 A.prototype.varA 總是會(huì)被 this.varA 遮蔽,
// 那么將 varA 加入到原型(prototype)中的目的是什么?
A.prototype = {
  varA : null,  // 既然它沒有任何作用,干嘛不將 varA 從原型(prototype)去掉?
      // 也許作為一種在隱藏類中優(yōu)化分配空間的考慮?
      // https://developers.google.com/speed/articles/optimizing-javascript#Initializing instance variables
      // 將會(huì)驗(yàn)證如果 varA 在每個(gè)實(shí)例不被特別初始化會(huì)是什么情況。
  doSomething : function(){
    // ...
  }
}

當(dāng)你 var a1 = new A();js內(nèi)部就會(huì)設(shè)置a1.[[prototype]] == A.prototype .

如果你再 var a2 = new A();那么 a1.doSomething 事實(shí)上會(huì)指向Object.getPrototypeOf(a1).doSomething,

它就是你在 A.prototype.doSomething 中定義的內(nèi)容。

比如:Object.getPrototypeOf(a1).doSomething == Object.getPrototypeOf(a2).doSomething == A.prototype.doSomething。

prototype 是用于類型的,而 Object.getPrototypeOf() 是用于實(shí)例的(instances),兩者功能一致。

var Fx = function(){};
    var fx = new Fx();

相當(dāng)于

var fx = new Object();
    fx[[prototype]] = Fx.prototype;
    Fx.call(fx);

在用原型繼承編寫復(fù)雜代碼前理解原型繼承模型十分重要。同時(shí),還要清楚代碼中原型鏈的長(zhǎng)度,并在必要時(shí)結(jié)束原型鏈,以避免可能存在的性能問題。此外,除非為了兼容新 JavaScript 特性,否則,永遠(yuǎn)不要擴(kuò)展原生的對(duì)象原型。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80968.html

相關(guān)文章

  • 你是否理解jsObjectFunction原型

    摘要:原型對(duì)象是由創(chuàng)建的,因此原型對(duì)象的構(gòu)造函數(shù)是構(gòu)造函數(shù)也可以是稱為對(duì)象,原型對(duì)象也就繼承了其生父構(gòu)造函數(shù)中的數(shù)據(jù),也同時(shí)繼承了原型對(duì)象的數(shù)據(jù)。當(dāng)然這條原型鏈中的數(shù)據(jù),會(huì)被還是還是這類構(gòu)造函數(shù)繼承,但是不會(huì)被這些繼承,他們不處于同一個(gè)鏈條上。 js中,F(xiàn)unction的本質(zhì)是什么?Object的本質(zhì)又是什么?js中有幾條原型鏈? showImg(https://segmentfault.c...

    itvincent 評(píng)論0 收藏0
  • 面向?qū)ο?em>的 JavaScript

    摘要:是完全的面向?qū)ο笳Z(yǔ)言,它們通過類的形式組織函數(shù)和變量,使之不能脫離對(duì)象存在。而在基于原型的面向?qū)ο蠓绞街?,?duì)象則是依靠構(gòu)造器利用原型構(gòu)造出來(lái)的。 JavaScript 函數(shù)式腳本語(yǔ)言特性以及其看似隨意的編寫風(fēng)格,導(dǎo)致長(zhǎng)期以來(lái)人們對(duì)這一門語(yǔ)言的誤解,即認(rèn)為 JavaScript 不是一門面向?qū)ο蟮恼Z(yǔ)言,或者只是部分具備一些面向?qū)ο蟮奶卣鳌1疚膶⒒貧w面向?qū)ο蟊疽?,從?duì)語(yǔ)言感悟的角度闡述為什...

    novo 評(píng)論0 收藏0
  • js繼承理解

    摘要:創(chuàng)建自定義的構(gòu)造函數(shù)之后,其原型對(duì)象只會(huì)取得屬性,其他方法都是從繼承來(lái)的。優(yōu)缺點(diǎn)寄生式繼承在主要考慮對(duì)象而不是創(chuàng)建自定義類型和構(gòu)造函數(shù)時(shí),是十分有用的。 原文鏈接:https://kongchenglc.coding.me... 1.原型鏈 ??js的繼承機(jī)制不同于傳統(tǒng)的面向?qū)ο笳Z(yǔ)言,采用原型鏈實(shí)現(xiàn)繼承,基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。理解原型鏈必須先理...

    BlackFlagBin 評(píng)論0 收藏0
  • 深入理解 js繼承原型

    摘要:原型鏈與繼承當(dāng)談到繼承時(shí),只有一種結(jié)構(gòu)對(duì)象。如果對(duì)該圖不怎么理解,不要著急,繼續(xù)往下看基于原型鏈的繼承對(duì)象是動(dòng)態(tài)的屬性包指其自己的屬性。當(dāng)使用操作符來(lái)作用這個(gè)函數(shù)時(shí),它就可以被稱為構(gòu)造方法構(gòu)造函數(shù)。 原型鏈與繼承 當(dāng)談到繼承時(shí),JavaScript 只有一種結(jié)構(gòu):對(duì)象。每個(gè)實(shí)例對(duì)象(object )都有一個(gè)私有屬性(稱之為proto)指向它的原型對(duì)象(prototype)。該原型對(duì)象也...

    xingqiba 評(píng)論0 收藏0
  • js對(duì)象詳解(JavaScript對(duì)象深度剖析,深度理解js對(duì)象)

    摘要:對(duì)象詳解對(duì)象深度剖析,深度理解對(duì)象這算是醞釀很久的一篇文章了。用空構(gòu)造函數(shù)設(shè)置類名每個(gè)對(duì)象都共享相同屬性每個(gè)對(duì)象共享一個(gè)方法版本,省內(nèi)存。 js對(duì)象詳解(JavaScript對(duì)象深度剖析,深度理解js對(duì)象) 這算是醞釀很久的一篇文章了。 JavaScript作為一個(gè)基于對(duì)象(沒有類的概念)的語(yǔ)言,從入門到精通到放棄一直會(huì)被對(duì)象這個(gè)問題圍繞。 平時(shí)發(fā)的文章基本都是開發(fā)中遇到的問題和對(duì)...

    CatalpaFlat 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<