亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解 javascript對(duì)象創(chuàng)建模式

 更新時(shí)間:2020年10月30日 10:54:17   作者:張懟懟  
這篇文章主要介紹了詳解 javascript對(duì)象創(chuàng)建模式的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)JavaScript的相關(guān)知識(shí)。感興趣的朋友可以了解下

創(chuàng)建模式

在javascript中,主要有以下幾種創(chuàng)建模式:

工廠模式
構(gòu)造函數(shù)模式
原型模式
組合模式
動(dòng)態(tài)原型模式
寄生構(gòu)造函數(shù)模式
穩(wěn)妥構(gòu)造模式

工廠模式

工廠模式是軟件工程領(lǐng)域一種廣為人知的設(shè)計(jì)模式。javascript實(shí)現(xiàn)方式:

function createPerson(name, obj, job) {
    var o = new Object();
    o.name = name;
    o.obj = obj;
    o.job = job;
    o.sayName = function() {
      alert(this.name);
    }
    return o;
  }
  
  var person1 = createPerson("Nicholas", 29, "software Enginner");
  var person2 = createPerson("Greg", 27, "Doctor");

工廠模式雖然解決了創(chuàng)建多個(gè)相似對(duì)象的問(wèn)題,但卻沒(méi)有解決對(duì)象識(shí)別問(wèn)題

構(gòu)造函數(shù)模式

function Person(name, age, job) {
    this.name = name;
    this.age = name;
    this.job = name;
    this.sayName = function () {
      alert(this.name);
    }
  }
  
  var person1 = new Person("Nicholas", 29, "Software Engineer");
  var person2 = new Person("Greg", 27, "Doctor");
  
  person1 instanceof Person; // true
  person1 instanceof Object; // true
  
  person2 instanceof Person; // true
  person2 instanceof Object; // true

new操作符實(shí)現(xiàn)原理請(qǐng)查看文章附錄

不同于工廠模式,構(gòu)造函數(shù)模式

沒(méi)有顯示創(chuàng)建對(duì)象

直接將屬性和方法賦值給了this對(duì)象

沒(méi)有return語(yǔ)句

解決了對(duì)象識(shí)別問(wèn)題

但是構(gòu)造函數(shù)模式同樣存在問(wèn)題,就是每個(gè)方法都要在每個(gè)實(shí)例上重新申明一遍。person1和person2都有一個(gè)名為 sayName() 的方法,但那兩個(gè)方法不是同一個(gè)Function實(shí)例。(在javascript中,函數(shù)實(shí)質(zhì)上也是對(duì)象,因此每定義一個(gè)函數(shù),也就是實(shí)例化一個(gè)對(duì)象。)

通過(guò)吧函數(shù)定義轉(zhuǎn)移到構(gòu)造函數(shù)外部可以解決這個(gè)問(wèn)題:

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
  }
  function sayName() {
    alert(this.name);
  }
  var person1 = new Person("Nicholas", 29, "Software Engineer");
  var person2 = new Person("Greg", 27, "Doctor");

但這種方式又帶來(lái)了一個(gè)新的問(wèn)題,我們?cè)谌謩?chuàng)建了一個(gè)全局函數(shù)。

需要注意一點(diǎn),按照慣例,構(gòu)造函數(shù)始終應(yīng)該以一個(gè)大寫(xiě)字母開(kāi)頭,而非構(gòu)造函數(shù)應(yīng)該以一個(gè)小寫(xiě)字母開(kāi)頭。這主要用于區(qū)別構(gòu)造函數(shù)和非構(gòu)造函數(shù),因?yàn)闃?gòu)造函數(shù)本身也是函數(shù)。

原型模式

我們創(chuàng)建的每個(gè)函數(shù)都有一個(gè) prototype (原型)屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象,而這個(gè)對(duì)象的用途可以由特定類型的所有實(shí)例共享的屬性和方法。

函數(shù)原型對(duì)象請(qǐng)查看附錄

通過(guò)原型模式創(chuàng)建對(duì)象,我們不必在構(gòu)造函數(shù)中定義對(duì)象實(shí)例的信息,同時(shí)實(shí)例化多個(gè)對(duì)象,每個(gè)對(duì)象不會(huì)再申明一個(gè)新的函數(shù)。

可以看到, person1.sayName 和 person2.sayName 都指向了同一個(gè)函數(shù)。

但是原型模式的缺點(diǎn)也是顯而易見(jiàn)的。

首先原型模式省略了構(gòu)造函數(shù)模式傳遞參數(shù)這一環(huán)節(jié),結(jié)果導(dǎo)致所有實(shí)例的初始值在默認(rèn)情況下都是相同的屬性值。

更重要的是,因?yàn)閷傩院头椒ǘ挤胖迷谠蛯?duì)象上,實(shí)質(zhì)上原型上的屬性是 被所有實(shí)例所共享的 。對(duì)于包含基本值的屬性還表現(xiàn)正常,改變屬性值,只是在實(shí)例上添加一個(gè)同名屬性。但對(duì)于引用類型值的屬性來(lái)說(shuō),這可能是個(gè)災(zāi)難。

function Person() {}
  
  Person.prototype = {
    constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    friends: ["shelby", "Court"],
    sayName: function() {
      alert(this.name);
    }
  };
  
  var person1 = new Person();
  var person2 = new Person();
  
  person1.friends.push("Van");
  
  person1.friends; // ["shelby", "Court", "Van"]
  person2.friends; // ["shelby", "Court", "Van"]

組合模式

創(chuàng)建自定義類型最常見(jiàn)的方式,就是組合使用構(gòu)造函數(shù)模式和原型模式。構(gòu)造模式用于定義實(shí)例屬性,而原型模式用于定義方法和共享屬性。

這樣,每個(gè)實(shí)例都會(huì)有自己的一份實(shí)例屬性副本,但同時(shí)又共享方法的引用。

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby", "Court"];
  }
  
  Person.prototype.sayName = function() {
    alert(this.name);
  }
  
  var person1 = new Person("Nicholas", 29, "Software Enginner");
  var person2 = new Person("Greg", 27, "Doctor");
  
  person1.friends.push("Van");
  
  person1.firends; // ["Shelby", "Court", "Van"];
  person2.firends; // ["Shelby", "Court"]
  
  person1.firends === person2.firends; // false
  person1.sayName === person2.sayName; // true

動(dòng)態(tài)原型模式

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    
    if (typeof this.sayName != "function") {
      Person.prototype.sayName = function() {
        alert(this.name);
      }
    }
  }

寄生構(gòu)造函數(shù)模式

寄生模式的基本概念就是創(chuàng)建一個(gè)函數(shù),該函數(shù)的作用僅僅是封裝創(chuàng)建對(duì)象的代碼,然后再返回新創(chuàng)建的對(duì)象。

function Person(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job.
    
    o.sayName = function() {
      alert(this.name);
    }
  }
  
  var person1 = new Person("Nicholas", 29, "Software Engineer");
  person1.sayName(); // "Nicholas"

看起來(lái),除了使用new操作符之外,這個(gè)模式和工廠模式其實(shí)是一模一樣的。
這個(gè)模式可以在特殊的情況下用來(lái)作為對(duì)象創(chuàng)建構(gòu)造函數(shù)。
假設(shè)我們需要一個(gè)具有額外方法的特殊數(shù)組類型。由于不能直接修改Array構(gòu)造函數(shù),因此可以使用這個(gè)模式。

  function SpecialArray() {
    var values = [];
    
    values.push.push(values, arguments);
    values.toPipedString = function() {
      return this.join("|");
    }
    
    return values;
  }
  
  var colors = new SpecialArray("red", "blue", "green");
  colors.toPipedString(); // "red|blue|green"

該模式主要缺點(diǎn):
返回的對(duì)象和構(gòu)造函數(shù)或構(gòu)造函數(shù)的原型屬性間沒(méi)有關(guān)系,不·能依賴instanceof來(lái)確定對(duì)象類型。
在其他模式能夠使用的情況下,盡量不要使用這種模式。

穩(wěn)妥構(gòu)造函數(shù)模式

  function Person(name, age, job) {
    var o = new Object();
    var name = name;
    var age = age;
    var job = jbo;
    
    o.sayName = function() {
      alert(name);
    }
  }
  
  var person1 = Person("Nicholas", 29, "Software Enginner");
  firend.sayName(); // "Nicholas"
  1. 附錄
  2. new 操作符

new操作符實(shí)際上會(huì)經(jīng)歷4個(gè)步驟:

  1. 創(chuàng)建一個(gè)空的簡(jiǎn)單JavaScript對(duì)象(即**{}**);
  2. 鏈接該對(duì)象(設(shè)置該對(duì)象的constructor)到另一個(gè)對(duì)象 ;
  3. 將步驟1新創(chuàng)建的對(duì)象作為**this**的上下文 ;
  4. 如果該函數(shù)沒(méi)有返回對(duì)象,則返回**this**。
  function new(func) {
    var o = {};
    o.__proto__ = func.prototype;
    var result = func.apply(o, arguments);
    return typeof result === "object" ? object : o;
  }

函數(shù)原型對(duì)象

理解原型對(duì)象

無(wú)論什么時(shí)候,只要?jiǎng)?chuàng)建一個(gè)新函數(shù),就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè)prototype屬性,這個(gè)屬性指向函數(shù)的原型對(duì)象。在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)construtor(構(gòu)造函數(shù))屬性,這個(gè)屬性包含一個(gè)指向prototype屬性所在函數(shù)的指針。

在創(chuàng)建了一個(gè)自定義的構(gòu)造函數(shù)之后,其原型對(duì)象只會(huì)取得construtoe屬性,至于其他屬性,則都是從Object繼承而來(lái)。當(dāng)調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)新實(shí)例時(shí),該實(shí)例的內(nèi)部將包含一個(gè)指針(內(nèi)部屬性),指向構(gòu)造函數(shù)的原型對(duì)象,這個(gè)指針叫[[Prototype]]。在多數(shù)瀏覽器中,每個(gè)對(duì)象都支持一個(gè)屬性__proto__來(lái)調(diào)用[[Prototype]]。

雖然所有實(shí)現(xiàn)都無(wú)法直接訪問(wèn)[[Prototype]],但可以通過(guò)isPrototype方法來(lái)確定對(duì)象之間是否存在關(guān)系。

我們測(cè)試了person1和person2,都返回了true。因?yàn)樗麄儍?nèi)部都有一個(gè)指向Person.prototype的指針。

Object.getPrototype()可以返回對(duì)象的原型對(duì)象。

每當(dāng)代碼讀取某個(gè)對(duì)象的屬性時(shí),都會(huì)執(zhí)行一次搜索,目標(biāo)是具有給定名字的屬性。搜索首先會(huì)從對(duì)象本身開(kāi)始,如果在實(shí)例中找到了對(duì)應(yīng)的屬性,則返回該屬性的值。如果沒(méi)找到,則繼續(xù)搜索指針指向的原型對(duì)象。這也是為什么我們?cè)趐erson1和person2兩個(gè)實(shí)例中,并沒(méi)有定義sayName這個(gè)屬性,但仍能夠正常使用。
我們?cè)谡{(diào)用person1.sayName()是,會(huì)執(zhí)行兩次搜索。首先,解析器會(huì)問(wèn):“實(shí)例person1有sayName屬性嗎?”,答:“沒(méi)有”。然后他繼續(xù)搜索,再問(wèn):“person1的原型有sayName屬性嗎?”,答:“有”。于是,它就讀取保存在原型中的函數(shù)。

雖然我們能夠通過(guò)實(shí)例訪問(wèn)原型的屬性,但卻不能重新原型的屬性。
如果我們?cè)趯?shí)例上添加屬性名,而這個(gè)屬性名又與原型中的屬性名相同,即我們希望在實(shí)例中重寫(xiě)屬性。

  function Person() {}
  Person.prototype.name = 'Nicholas';
  
  var person1 = new Person();
  var person2 = new Person();
  
  person1.name === person2.name; // true
  person1.name = 'Greg';
  
  person1.name === person2.name; // false
  person1.name; // 'Greg'
  person2.name; // 'Nicholas'
  
  person1.__proto__.name; // 'Nicholas'

事實(shí)上,當(dāng)我們重寫(xiě)原型屬性時(shí),只是在實(shí)例上添加了一個(gè)新屬性。當(dāng)我們把實(shí)例上的屬性刪除后,又會(huì)暴露出原型屬性。

  delete person1.name;
  person1.name; // 'Nicholas'

使用hasOwnProperty()函數(shù)能判斷屬性是否在實(shí)例上。

  person1.hasOwnProperty('name'); // false
  person1.name = 'Greg';
  person1.hasOwnProperty('name'); // true

以上就是詳解 javascript對(duì)象創(chuàng)建模式的詳細(xì)內(nèi)容,更多關(guān)于Java 創(chuàng)建模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論