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

資訊專欄INFORMATION COLUMN

JS代碼復用模式

nanfeiyan / 3368人閱讀

摘要:那么在代碼復用方面都有哪些方法構(gòu)造模式構(gòu)造函數(shù)與普通函數(shù)的唯一區(qū)別在于調(diào)用方式不同構(gòu)造函數(shù)首字母大寫只是慣例,任何函數(shù)都可以用關(guān)鍵字來作為構(gòu)造函數(shù)調(diào)用構(gòu)造函數(shù)普通函數(shù)。

復用是一項非常重要的生活技能,因為生命是有限的,無意義的重復等于浪費生命。作為一個程序開發(fā)者,代碼的復用既是一種能力,也是對積極生活的一種態(tài)度。那么JS 在代碼復用方面都有哪些方法?
...................................................................................................
構(gòu)造模式

構(gòu)造函數(shù)與普通函數(shù)的唯一區(qū)別在于調(diào)用方式不同(構(gòu)造函數(shù)首字母大寫只是慣例),任何函數(shù)都可以用new關(guān)鍵字來作為構(gòu)造函數(shù)調(diào)用(構(gòu)造函數(shù) = new + 普通函數(shù))。

function Parent() {
  this.name = "jim";
  this.say = function() {
    console.log(this.name);
  };
  console.log(this.name);
}
Parent(); // 輸出 jim
console.log(Parent); // 輸出 Parent?(){/* 函數(shù)體-略 */}

var child1 = new Parent(); // 輸出 jim 構(gòu)造函數(shù)創(chuàng)建 child1 對象(解析執(zhí)行)
var child2 = new Parent(); // 輸出 jim 構(gòu)造函數(shù)創(chuàng)建 child2 對象(解析執(zhí)行)

console.log(child1); // 輸出 Parent?{name: "jim", say: ? ()}
console.log(child1.say); // 輸出 ? ()?{/* 函數(shù)體-略 */}

child1.say(); // 輸出 jim
child2.say(); // 輸出 jim

console.log(child1.name); // 輸出 jim (child1 繼承了 Parent name)
console.log(child2.name); // 輸出 jim (child2 繼承了 Parent name)

child1.name = "tom1"; // 修改 child 的 name 屬性
child2.name = "tom2"; // 修改 child 的 name 屬性

child1.say(); // 輸出 tom1(說明 child 本地實例化了name屬性 )
child2.say(); // 輸出 tom2(說明 child 本地實例化了name屬性 )
console.log(child1.name); // 輸出 tom1(說明 child 本地實例化了name屬性 )
console.log(child2.name); // 輸出 tom2(說明 child 本地實例化了name屬性 )

delete child1.name; // 刪除 child1 的 name 屬性
delete child2.name; // 刪除 child2 的 name 屬性

console.log(child1.name); // 輸出 undefined(說明 child1 本地實例化name屬性已刪除 )
console.log(child2.name); // 輸出 undefined(說明 child2 本地實例化name屬性已刪除 )

Parent(); // 輸出 jim (說明構(gòu)造函數(shù)屬性 和 構(gòu)造對象屬性 沒有關(guān)系)

缺點:無法復用父對象屬性方法,當子對象數(shù)量變多,反復使用 new 重新創(chuàng)建父對象.

原型模式

我們知道所有引用類型都是 Object,也就是說引用類型的原型是 Object,他們是一個繼承的關(guān)系。另外,原型的屬性可以自定義。

function fn() {
  this.keyThis = ["fnThisValue"];
}
// name: "fn" prototype: {constructor: fn()} __proto__: Object
// 函數(shù)名是 fn
// 函數(shù) prototype 指向一個對象,該對象的屬性constructor 指向函數(shù)自身
// 函數(shù) __proto__ 指向 Object(重點 __proto__ 是一個原型引用指針,指向父級原型)
// 此時fn 未執(zhí)行, this 雖然指向window , 但是 keyThis 并未聲明和賦值

// 以上是 JS 內(nèi)部已經(jīng)實現(xiàn)好的,下面我們來自定義一個原型屬性
fn.prototype.keyProto = ["fnProtoValue"];
console.log(fn.prototype);
// 輸出 {keyProto: ["fnProtoValue"], constructor: fn(),__proto__: Object}

var foo = new fn(); // fn() 執(zhí)行, this指向window,key1聲明和賦值
console.log(foo);
// 輸出
// fn{
//    keyThis:["fooThisValue"],
//    __proto__:{ keyProto: ["fnProtoValue"], constructor: fn(), __proto__: Object}
// }
// foo 僅僅是一個構(gòu)造對象(重點對象沒有原型屬性),原型引用指針__proto__指向 fn 的原型
// 原型鏈 就是 __proto__:{__proto__:{···}}

console.log(foo.keyThis); // 輸出 ["fooThisValue"]
console.log(foo.keyProto); // 輸出 ["fnProtoValue"]

foo.keyThis.push("fooThis");
foo.keyProto.push("fooProto");

console.log(foo);
// 輸出
// fn{
//    keyThis:["fooThisValue", "fooThis"],
//    __proto__:{ keyProto: ["fnProtoValue", "fooThis"], constructor: fn(), __proto__: Object}
// }
// foo 的原型屬性竟然被修改了,這應該不是我們想要的(小本本記下來),所以父級常量最好用 this 來定義

console.log(fn.prototype);
// 輸出{ keyProto: ["fnProtoValue", "fooThis"], constructor: fn(), __proto__: Object}

缺點:雖然復用父對象屬性方法,當子對象數(shù)量變多,反復使用 new 重新創(chuàng)建父對象.

借用模式

在 JS 基礎(chǔ)數(shù)據(jù)類型操作系列(四)函數(shù) 中,我們介紹了 call,apply 和 bind 的函數(shù)作用域借用操作,這也是一種代碼復用的好方法。

function Parent() {
  this.keyThis = ["fnThisValue"];
}
Parent.prototype.keyProto = ["fnProtoValue"];
function Child() {
  Parent.call(this);
  console.log(this.keyThis); // 輸出 ["fnThisValue"]
  console.log(this.keyProto); // 輸出 undefined
}
Child();
// 這種借用只能夠針對 this 綁定的屬性方法起作用。

var jim = new Child();
console.log(jim.keyThis); // 輸出 ["fnThisValue"]
console.log(jim.keyProto); // 輸出 undefined
// 這種借用只能夠針對 this 綁定的屬性方法起作用。
代理模式
function inherit(parent, child) {
  var F = function() {};
  F.prototype = parent.prototype;
  child.prototype = new F();
  child.prototype.constructor = child;
}

function Parent() {
  this.keyThis = ["fnThisValue"];
}
Parent.prototype.keyProto = ["fnProtoValue"];

function Child() {}
inherit(Parent, Child);

var jim = new Child();
console.log(jim.keyThis); // 輸出 undefined
console.log(jim.keyProto); // 輸出 ["fnProtoValue"]

缺點:只是代理了原型

標準模式

在 ES 5 中,提供了Object.create()方法來實現(xiàn)原型構(gòu)造繼承(語法糖)。
Object.create()方法創(chuàng)建一個新對象,使用現(xiàn)有的對象來提供新創(chuàng)建的對象的__proto__

語法 :Object.create(proto, [propertiesObject]) 。

第二個可選參數(shù)是 null 或一個對象,添加到新創(chuàng)建對象的自定義可枚舉屬性,對應 Object.defineProperties()的第二個參數(shù)。

function Parent() {}
Parent.prototype.keyProto = ["fnProtoValue"];

var jim = Object.create(Parent, {
  key: { value: "val" }
});

console.log(jim); // 輸出 Function?{key: "val",__proto__: Parent()}
jim.hasOwnProperty("key");


var Fn = {
    key:"value"
}
Object.create(Fn)
// {__proto__:{ key:"value"}}
克隆模式

通過復制屬性來實現(xiàn)繼承

淺克隆

簡單對象,單層克隆

function extend(parent, child) {
  var i;
  child = child || {};
  for (i in parent) {
    if (parent.hasOwnProperty(i)) {
      child[i] = parent[i]; // 這里只是引用, 并非實例化
    }
  }
  return child;
}

var Parent = {
    key:"value",
    arr:[1,2,3,4],
    obj:{
        key:"value",
        arr:[1,2,3,4],
    }
}
var kid = extend(Parent)
kid.arr.push(4);
console.log(Parent.arr)  // 輸出 [1,2,3,4,4]
深克隆

復雜對象,遞歸克隆

function extendDeep(parent, child) {
  var i,
    toStr = Object.prototype.toString,
    astr = "[object Array]";
  child = child || {};
  for (i in parent) {
    if (parent.hasOwnProperty(i)) {
      if (typeof parent[i] === "object") {
        child[i] = toStr.call(parent[i]) === astr ? [] : {};
        arguments.callee(parent[i], child[i]);
      } else {
        child[i] = parent[i];
      }
    }
  }
  return child;
}
var Parent = {
    key:"value",
    arr:[1,2,3,4],
    obj:{
        key:"value",
        arr:[1,2,3,4],
    }
}
var kid = extendDeep(Parent)
kid.arr.push(4);
console.log(Parent.arr)  // 輸出 [1,2,3,4]

缺點:針對的是對象,不是函數(shù),當然對象用這個是最好的

總結(jié)

綜上了解,我們想要一個既可以繼承this屬性,又可以繼承prototype屬性的方法。繼承this屬性最好用的是借用模式,繼承prototype屬性最好用的是Object.create()標準模式。

function parent() {
  this.money = 1000;
}
parent.prototype.say = function(money) {
  console.log("I have " + (this.money + money));
}

function inherit(parent,childParams){
    function Child() {
        parent.call(this);      // 借用 父級 this 屬性
    }
    childParams = childParams || {}; // 定義額外參數(shù)
    Child.prototype = Object.create(parent.prototype,childParams);
    // parent.prototype 指向原型對象parent Prototype
    // Object.create(parent.prototype)
    // 輸出 {__proto__:{ say:? (money),constructor:? parent(), __proto__:Object}}
    Child.prototype.constructor = Child; // 原型的構(gòu)造函數(shù)應該永遠指向自身
    return new Child()
}

var jim = inherit(parent);
var tom = inherit(parent,{key:{value:500}});
jim.say(100);   //輸出 I have 1100
tom.say(500);   //輸出 I have 1100
tom.key         //輸出 500

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

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

相關(guān)文章

  • JavaScript代碼復用模式

    摘要:如下代碼所示,可以使用構(gòu)造函數(shù)來創(chuàng)建父對象,這樣做的話,自身的屬性和構(gòu)造函數(shù)的原型的屬性都將被繼承。方法繼承自對象這是中構(gòu)造函數(shù)鏈的一個示例。 代碼復用及其原則 代碼復用,顧名思義就是對曾經(jīng)編寫過的代碼的一部分甚至全部重新加以利用,從而構(gòu)建新的程序。在談及代碼復用的時候,我們首先可以想到的是繼承性。代碼復用的原則是: 優(yōu)先使用對象組合,而不是類繼承 在js中,由于沒有類的概念,因此實例...

    bergwhite 評論0 收藏0
  • 《Node.js設(shè)計模式》歡迎來到Node.js平臺

    摘要:事件多路復用器收集資源的事件并且把這些事件放入隊列中,直到事件被處理時都是阻塞狀態(tài)。最后,處理事件多路復用器返回的每個事件,此時,與系統(tǒng)資源相關(guān)聯(lián)的事件將被讀并且在整個操作中都是非阻塞的。 本系列文章為《Node.js Design Patterns Second Edition》的原文翻譯和讀書筆記,在GitHub連載更新,同步翻譯版鏈接。 歡迎關(guān)注我的專欄,之后的博文將在專欄同步:...

    Paul_King 評論0 收藏0
  • JS學習筆記 - 代碼復用

    摘要:本文章記錄本人在學習中看書理解到的一些東西,加深記憶和并且整理記錄下來,方便之后的復習。但是在開發(fā)的過程中,并不是所有的代碼復用都會使用到繼承。而且整個代碼都無法按照預期來運行。為了修復綁定對象與方法之間的關(guān)系。 本文章記錄本人在學習 JavaScript 中看書理解到的一些東西,加深記憶和并且整理記錄下來,方便之后的復習。 js 中復用代碼 說道代碼復用,一般都會涉及到對...

    cheng10 評論0 收藏0
  • MVC MVP MVVM

    摘要:,的事件回調(diào)函數(shù)中調(diào)用的操作方法。以為例調(diào)用關(guān)系模式實際就是將中的改名為,調(diào)用過程基本一致,最大的改良是間的雙向綁定。和間,有一個對象,可以操作修改,使用。 參考:MVC,MVP 和 MVVM 的圖示 - 阮一峰http://www.ruanyifeng.com/blo...Web開發(fā)的MVVM模式http://www.cnblogs.com/dxy198...界面之下:還原真實的MV...

    wushuiyong 評論0 收藏0
  • MVC MVP MVVM

    摘要:,的事件回調(diào)函數(shù)中調(diào)用的操作方法。以為例調(diào)用關(guān)系模式實際就是將中的改名為,調(diào)用過程基本一致,最大的改良是間的雙向綁定。和間,有一個對象,可以操作修改,使用。 參考:MVC,MVP 和 MVVM 的圖示 - 阮一峰http://www.ruanyifeng.com/blo...Web開發(fā)的MVVM模式http://www.cnblogs.com/dxy198...界面之下:還原真實的MV...

    Tangpj 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<