http響應狀態碼「javascript內置對象有哪些」

Javascript有多種創建對象的方式,新手和老手都可能感到不知所措,不確定應該使用哪種方式。文本將介紹常見的對象常見模式和最佳的實踐。

Javascript對象創建模式
Javascript對象創建模式

對象字面量:Object Literals

創建對象最簡單的方式就是對象字面量。Javascript總是吹噓能夠「無中生有」地創建對象——不需要類、不需要模板、不需要原型——just poof!,一個有方法和數據的對象就出現了。

var o = {
    x: 42,
    y: 3.14,
    f: function() {},
    g: function() {}
};

缺點

如果需要在其他地方創建相同類型的對象,將要複製粘貼對象的方法、數據和初始化的代碼,導致大量重複代碼。需要一種能夠批量創建同類型對象的方法,而不僅僅是一個對象。

工廠模式:Factory Functions

這是創建相同結構、接口和實現的對象最簡單的方式。而不是直接創建對象字面量,而是將對象字面量作為函數的返回值。這樣,如果需要多次或多個地方創建相同類型的對象時只需要調用一個函數:

function thing() {
  return {
    x: 42,
    y: 3.14,
    f: function() {},
    g: function() {}
  };
}
var o = thing();

缺點

這種Javascript對象創建方法可能會導致內存膨脹,因為每一個對象都包含了工廠函數的獨立副本。理想情況下,我們希望每個對象只共享其功能的一個副本。

構造函數模式

可以創建特定類型的對象, 類似於Array, Date等原生JS的對象.其實現方法如下:

function Student(name,age){
    this.name=name;
    this.age=age;
    this.myName=function(){
        alert(this.name);
    };
}
var student1_ = new Student('aaa',15);
var student2_ = new Student('bbb',18);

缺點

每次實例化一個對象都會把構造器里的所有方法重新創建一次,多次創建會造成內存開銷增加的問題。

原型鏈:Prototype Chains

Javascript提供了一種內置的在對象之間共享數據的機制,稱為原型鏈。當訪問對象的屬性時,它可以通過委託給其他對象來滿足該請求。可以利用這一點來修改工廠函數,使它創建的每個對象只包含自己特有的數據,而對其他屬性的請求則全部委託給原型鏈上共有的一個對象:

var thingPrototype = {
  f: function() {},
  g: function() {}
};

function thing() {
  var o = Object.create(thingPrototype);

  o.x = 42;
  o.y = 3.14;

  return o;
}

var o = thing();

事實上,這是一種常見的模式,語言已經內置了對它的支持。不需要創建自己的共享對象(原型對象)。相反,會自動為每個函數創建一個原型對象,可以將共享數據放在那裡:

thing.prototype.f = function() {};
thing.prototype.g = function() {};

function thing() {
  var o = Object.create(thing.prototype);

  o.x = 42;
  o.y = 3.14;

  return o;
}

var o = thing();

缺點

會導致重複。上述thing函數的第一行和最後一行在每一個「委託原型的工廠函數」中都會重複一次,幾乎沒有區別。

ES5類:ES5 Classes

可以把那些重複的代碼抽出來,放進一個自定義函數里來隔離它們。這個函數會創建一個對象,並與其他某個任意函數(參數函數)的原型建立委託(繼承)關係,然後把新創建的對象作為參數,調用這個函數(參數函數),最後返回這個新的對象。

function create(fn) {
  var o = Object.create(fn.prototype);

  fn.call(o);

  return o;
}

// ...

Thing.prototype.f = function() {};
Thing.prototype.g = function() {};

function Thing() {
  this.x = 42;
  this.y = 3.14;
}

var o = create(Thing);

事實上,這也是一種常見的模式,Javascript有一些內置的支持。create定義的函數實際上是new關鍵字的基本版本,可以直接替換create為new(構造函數+原型鏈):

Thing.prototype.f = function() {};
Thing.prototype.g = function() {};

function Thing() {
  this.x = 42;
  this.y = 3.14;
}

var o = new Thing();

在ES5中,它們是對象創建函數,它將共享數據委託給原型對象,並依賴new關鍵字來處理重複邏輯。

缺點

冗長和醜陋,實現繼承更加冗長和醜陋。

ES6類:ES6 Classes

在ES6的類中,執行相同的操作提供了更清晰的語法:

class Thing {
  constructor() {
    this.x = 42;
    this.y = 3.14;
  }

  f() {}
  g() {}
}

const o = new Thing();

比較

多年以來,Javascript開發者們與原型鏈的關係總是若即若離,糾纏不清。而今天最有可能遇到的兩種創建對象的方式,一種是強烈依賴原型鏈的class語法,另一種則是完全不依賴原型鏈的工廠函數語法。這兩種風格在性能和功能上有所不同——儘管差別不太大。

性能

今天Javascript引擎已經過如此大量優化,以至於很難通過Javascript代碼來推斷怎樣會比較快。關鍵在於測量方法。然而有時甚至測量都會讓我們失望。通常情況下,每六周發佈一次更新的Javascript引擎,有時性能會發生重大變化,我們之前進行的任何測量以及我們根據這些測量做出的任何決定都會立即出現。因此,經驗法則是支持最官方和最廣泛使用的語法,假設它將受到最嚴格的審查,並且在大多數時候是最高效的。目前來看class語法最符合這一點,class語法大約比返回字面量的工廠模式快3倍。

特點

隨着ES6的發佈,類與工廠模式之間曾經存在的幾點差異消失了。現在,工廠模式和類都能夠強制實現真正的私有數據:

  • 工廠模式通過閉包實現
  • 類通過weak maps實現

兩者都能實現多重繼承——工廠模式可以將其他屬性混入自己的對象,類也可以將其他屬性混入自己的原型,或者通過類工廠,通過代理也能實現。工廠函數和類也都可以在需要的時候返回任意對象,語法也都很簡單。

結論

考慮到所有事情,對Javascript對象創建的偏好是使用類語法。它是標準的,它簡單而乾淨,速度快,並且它提供了曾經只有工廠模式才能提供的所有功能

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/256107.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-15 12:33
下一篇 2024-12-15 12:33

相關推薦

發表回復

登錄後才能評論