中文字幕一区二区人妻电影,亚洲av无码一区二区乱子伦as ,亚洲精品无码永久在线观看,亚洲成aⅴ人片久青草影院按摩,亚洲黑人巨大videos

用JavaScript創(chuàng)建對象的現(xiàn)代方法

發(fā)布于:2021-01-19 09:56:45

0

105

0

客戶端 douglas crockford 前端 javascript 教程

在停滯了幾年之后,我們最近看到JavaScript語言開發(fā)取得了相當大的進展。ECMAScript5標準現(xiàn)在已經(jīng)有3年的歷史了,所有主要的瀏覽器供應商都在其當前版本中支持它。因此,現(xiàn)在也許正是真正接受新的語言特征并采用現(xiàn)代發(fā)展風格的時候。

如果JS不僅僅用于jQuery一行程序,那么您將需要一種結構化的方法。有很多方法可以用JS來構造代碼。一個偉大的也是非常常見的方法是使用對象和原型繼承。

老辦法

假設你建立了一個商店,你需要快遞產(chǎn)品。在以前的日子里,在ECMAScript5(ES5)之前,您可能會編寫如下內(nèi)容:

var Product = function(name) {
   this.name = name;
};
Product.prototype.showName = function() {alert(this.name);};

var myProduct = new Product("Super Fancy TV");
myProduct.showName();

實際上,這還不錯。您有一個構造函數(shù)來創(chuàng)建對象并將方法附加到原型。所有單個產(chǎn)品都有這些方法,但有幾個弱點需要考慮:

在JavaScript語言中沒有私有屬性。name的值可以隨時從外部更改。

  • 方法是分散的。即使你把它們放在一個地方,也沒有一個單一的結構來定義你的對象概念——就像許多其他面向對象語言中的類一樣。

  • 你很容易忘記使用“new”關鍵字。這不會引發(fā)錯誤,它只會導致完全不同的行為,可能會導致一些很難找到的真正討厭的bug。

  • 繼承將帶來更多問題。在JS社區(qū)中,沒有一個一致同意的方法來正確地執(zhí)行它。

由于這些原因,許多開發(fā)人員已經(jīng)創(chuàng)建了提供所有類型的對象創(chuàng)建和實例化邏輯的庫、框架和工具。其中許多引入了類(例如Prototype或Coffescript)。

如果你愿意,你可以走這條路,但我不推薦??赡芎茈y相信,但原型繼承實際上比基于類的繼承容易得多,甚至提供了額外的好處??纯雌渌脑驼Z言,比如IO或Self。正是舊的JavaScript語法使得原型難以使用

道格拉斯·克羅克福德開創(chuàng)了一種更好的方法。他寫了一篇短文對象.創(chuàng)建

方法已進入ES5標準-以稍微擴展的形式

對象.創(chuàng)建

好消息是,您不需要使用帶有ES5實現(xiàn)的現(xiàn)代瀏覽器。Mozilla開發(fā)者網(wǎng)絡有一個polyfill。它允許您使用創(chuàng)建對象的新方法,即使在IE8及以下的舊瀏覽器中也是如此。這一點很重要,因為IE7/IE8的市場份額總和仍約為9%。如果只針對Firefox、Chrome、Safari或Opera用戶,這不是問題。

if (!Object.create) {
   Object.create = function (o) {
       if (arguments.length > 1) {
           throw new Error('Object.create implementation only accepts the first parameter.');
       }
       function F() {}
       F.prototype = o;
       return new F();
   };
}

只需包括從上面的polyfill你將有一個對象.創(chuàng)建功能。代碼段的第一行檢查對象.創(chuàng)建已經(jīng)有了。這樣可以確保在當前瀏覽器提供本機實現(xiàn)的情況下,polyfill不會覆蓋本機實現(xiàn)。如果您需要其他ES5功能的額外多填充,可以使用Kris Kowal的ES5填充。

單獨對象

讓我們再看一看商店項目。如果您只想創(chuàng)建一個產(chǎn)品,則不需要對象.創(chuàng)建. 直接創(chuàng)建對象即可。

var myProduct = {
     price: 399.50,
     name: 'Super Fancy TV'
};

然而,這并不是最好的選擇。您可以從外部輕松地操縱對象的屬性,并且無法檢查或轉換指定的值??紤]像這樣的任務我的產(chǎn)品價格=-20。

像這樣的一個錯誤將確保你的公司銷售很多產(chǎn)品很快,并有真正高興的客戶-客戶收到20美元每購買。你的公司做不了多久!

多年的面向對象編程和設計經(jīng)驗告訴我們,要將對象的內(nèi)部狀態(tài)與其外部接口分離開來。通常需要將屬性私有化,并提供一些getter和setter方法。

接受者和接受者

ES5為使用getter和setter訪問屬性提供了一個很好的概念。不幸的是,沒有辦法讓它們在舊瀏覽器中運行——你不能只使用polyfill。所以在接下來的兩年左右,我們大多數(shù)人都沒有奢侈的使用它。同時,您可以使用許多方法(參見Stoyan Stefanov的JavaScript模式)。它們都有自己獨特的優(yōu)點和缺點。沒有單一的解決方案,所以歸根結底是口味的問題。以下是我通常做的:

帶有下劃線的前綴屬性,例如價格。這只是將屬性標記為private的約定。永遠不要從對象外部調(diào)用它們;違反此規(guī)則通常很容易發(fā)現(xiàn)。還有更復雜的方法使用基于閉包的模式來存檔真實的隱私(例如Stefanov的書)。我的觀點是,大多數(shù)情況下,它們不值得付出努力。

  • 提供一個以“set”開頭的setter方法,例如setPrice(value)。在舊瀏覽器中,無法覆蓋賦值運算符=。所以這是下一個最好的選擇。使用java和C++程序員。

  • 有時屬性可能只供內(nèi)部使用—或者您希望它只準備就緒。在這種情況下,只需省略適當?shù)姆椒āR虼烁玫膶崿F(xiàn)可能是這樣的。

var myProduct={u price:99.50,u name:'Grindle 3',

price:    function()  {return this._price;},
name:     function()  {return this._name;},
setPrice: function(p) {this._price = p;},

};

如果您想在設置價格之前檢查價格,現(xiàn)在可以輕松地執(zhí)行此操作。

setPrice: function(p) {
   if (p <= 0) {
       throw new Error("Price must be positive");
   }
   this._price = p;
}

真正的ECMAScript5實現(xiàn)甚至更好。它還有一個額外的好處,就是隱式地調(diào)用getter和setter。我的產(chǎn)品價格= 85.99. 最后,JavaScript支持統(tǒng)一訪問原則!

var myProduct = {
...
       get price() {return this._price;},
       set price(p) {
           if (p <= 0) { throw new Error("Price must be positive"); }
           this._price = p;
       },

...

原型

一家真正的商店當然會有很多產(chǎn)品。你不想從頭開始創(chuàng)造它們。你需要一個地方,在那里你可以放置共同的結構和行為。JS中通常的模式是為此創(chuàng)建一個父對象,一個產(chǎn)品的原型,所有其他產(chǎn)品都是從這個原型派生的。與對象.創(chuàng)建你用它來制造新產(chǎn)品。

var Product = {
   _price: 0,
   _name: '',

   price:    function()  {return this._price;},
   name:     function()  {return this._name;},
   setPrice: function(p) {this._price = p;},
   setName:  function(n) {this._name  = n;}
};

var product1 = Object.create(Product);
product1.setName('Grindle 3');
product1.setPrice(99.50);

初始化

為產(chǎn)品的所有新實例調(diào)用所有必要的設置程序可能有點不方便。為了避免這種情況,提供一個initialize方法,類似于其他語言的構造函數(shù)。

var Product = {
   ...
   init: function(name, price) {
       this._name = name;
       this._price = price;
   },
   ...
};
var product1 = Object.create(Product).init('Grindle 3', 99.50);

繼承

原型方法的一大優(yōu)點是實例化和繼承的統(tǒng)一。你不需要任何特別的東西-只要使用對象.創(chuàng)建為了繼承。

var Product = {
...
};

var Book = Object.create(Product);
Book._author = null;
Book._numPages = null;
Book.setAuthor   = function(author) {this._author = author;};
Book.setNumPages = function(num_pages) {this._numPages = num_pages;};
Book.author      = function() {return this.author();};
Book.numPages    = function() {return this.numPages();};

書是從產(chǎn)品中衍生出來的新事物。它沒有設置特定的值,比如名稱和價格,而是獲得額外的結構和行為。新的屬性author和numPages組成了這個結構,而它們的簡單getter和setter充當了一些實際行為的占位符示例。

缺點是多次調(diào)用Book是多余的,而且整個語法與定義基本對象有很大的不同。因此,通常構建一個小的extend函數(shù),使繼承更加方便。

Object.prototype.extend = function(newProperties) {
   for (var propertyName in newProperties) {
       this[propertyName] = newProperties[propertyName];
   }
   return this;
};

再說一次,在真正的ES5中你不需要這個。真實的對象.創(chuàng)建允許包含擴展名的第二個參數(shù)。

現(xiàn)在可以使用新的extend方法來分解代碼。

var Product = {
...
};

var Book = Object.create(Product).extend({
   _author: null,
   _numPages: null,
   setAuthor:   function(author) {this._author = author;},
   setNumPages: function(num_pages) {this._numPages = num_pages;},
   author:      function() {return this.author();},
   numPages:    function() {return this.numPages();}
});

內(nèi)原型遺傳

與基于靜態(tài)類的方法相比,對象和原型概念有許多優(yōu)點,例如:

繼承和實例化的統(tǒng)一。你可以用同樣的機制(對象.創(chuàng)建)從原型繼承或從原型生成實例(類似于類的用法)。實際上,這是一回事。

  • 價值觀的繼承。您可以從原型繼承值;無需在構造函數(shù)中設置默認值。

  • 原型的運行時修改。在JS中,運行時和編譯時沒有區(qū)別。您可以在程序執(zhí)行期間修改原型,而更多的靜態(tài)語言只允許在編譯器運行之前更改類。這不是原型繼承的直接優(yōu)勢,而是JS的動態(tài)特性。甚至還有基于類的語言,允許對類進行運行時修改——Ruby或Smalltalk就可以了。但是JavaScript的純對象方法使這變得簡單多了——如果您喜歡進行元編程,這將是一個真正的好處。

結論

對象.創(chuàng)建提供了一種更具吸引力的方法來使用原型,但仍然有一些怪癖。您必須實現(xiàn)自己的getter/setter、init和extend方法,才能在較舊的瀏覽器上工作。這些缺點最終會消失,當你放棄墊片和蓬勃發(fā)展的真正ECMAScript5-你已經(jīng)可以這樣做,如果IE8和以下是不關心你。在此之前,您可以使用對象.創(chuàng)建. 它可能比你想象的更快成為標準方法。

Marco Emrich于1993年開始專業(yè)軟件開發(fā),并使用了許多不同的語言和技術。他擁有計算機科學(德語)學位。并為弗勞恩霍夫IESE研究所做了一些關于生成編程的研究。目前,他受雇于德國IT培訓中心“網(wǎng)站管理員akademie”。在那里,他擔任作家、培訓師、軟件開發(fā)人員和項目經(jīng)理。他也喜歡為了好玩而編寫代碼,比如業(yè)余時間的項目幻想-卡片.net是的。