摘要:創建對象使用或者對象字面量都可以創建對象,但是這樣創建的對象過于簡單,不易于對象的屬性與方法的擴展與繼承。下面講的對象可以與中的做類比。通過調用構造函數創建的那個對象實例的原型對象。
創建對象
使用new Object()或者對象字面量都可以創建對象,但是這樣創建的對象過于簡單,不易于對象的屬性與方法的擴展與繼承。
下面講的對象可以與JavaEE中的bean做類比。
對,首先可能想到的是使用設計模式中的工廠模式
function createPizza(type) { var o = new Object(); o.type = type; o.bake = function() { alert("Start~"); alert(this.type); alert("End~"); }; return o; } var cheesePizza = createPizza("cheese"); var veggiePizza = createPizza("veggie"); cheesePizza.bake();優點
工廠模式解決了創建多個類似對象的問題
缺點對象無法識別,即創建出來的對象無法通過instanceof等分析出屬于哪種類型
構造函數模式用構造函數可用來創建特定類型的對象
// 構造函數首字母遵循OO語言慣例進行大寫 function Pizza(type) { this.type = type; this.bake = function() { alert("Start~"); alert(this.type); alert("End~"); }; } var cheesePizza = new Pizza("cheese"); var veggiePizza = new Pizza("veggie"); cheesePizza.bake();
與工廠模式相比:
沒有在方法中顯示創造對象(o);
直接將屬性與方法賦值給this;
沒有return語句
在用new的時候,會經歷一下4步:
創建一個新對象
將構造函數的作用域賦值給新對象(此時this指向新對象)
執行構造函數代碼(為對象添加屬性)
返回新對象
如果不使用new,將構造函數當做函數使用,則this指向Global對象(在瀏覽器中為window對象),當然,可以使用call方法來指定作用域,例如
var o = new Object(); Pizza.call(o, "salty"); o.bake();
使用構造函數方法,每個實例對象都有一個constructor構造函數屬性,該屬性指向Pizza(使用對象字面量、工廠模式方法創建的對象該屬性指向Object)
cheesePizza.constructor == Pizza
檢查某個對象屬于哪種類型,一般使用instanceof,cheesePizza同時屬于Pizza與Object(之所以屬于Object,是因為所有對象均繼承于Object)
cheesePizza instanceof Pizza; cheesePizza instanceof Object;優點
與工廠模式相比,構造函數模式能夠識別出對象類型
與下面的原型模式相比,能夠實現對象屬性的互相獨立,在引用類型屬性上很有用
每個實例對象的方法都是獨立的,導致方法不能夠共享
原型模式每個函數(不是實例對象)都有一個prototype屬性,該屬性是一個指針,指向一個對象,對象的用途是包含所有實例共享的屬性和方法。prototype通過調用構造函數創建的那個對象實例的原型對象。使用原型對象的好處是可以讓所有實例對象共享屬性與方法。
function Pizza() { } Pizza.prototype.type = "original" Pizza.prototype.bake = function() { alert("Start~"); alert(this.type); alert("End~"); }; var cheesePizza = new Pizza(); cheesePizza.type = "cheese"; var veggiePizza = new Pizza(); veggiePizza.type = "veggie"; cheesePizza.bake(); veggiePizza.bake();
各個對象共享屬性與方法,同時每個對象都可以建立自己的屬性,并屏蔽掉原型對象的同名屬性,因為共享屬性與方法,所以以下等式成立
cheesePizza.bake == veggiePizza.bake對象字面量重寫原型對象
也可以通過對象字面量來重寫整個原型對象:
Pizza.prototype = { type: "original", bake: function() { alert("Start~"); alert(this.type); alert("End~"); } }
這樣完全重寫,原型對象上的constructor屬性不再指向Pizza函數(全新的constructor指向Object),不過不影響通過instanceof來識別對象類型。如果constructor特別重要的話,可以顯式將它置為適當的值:
Pizza.prototype = { constructor: Pizza, type: "original", bake: function() { alert("Start~"); alert(this.type); alert("End~"); } }
不過這種方式會將constructor的屬性特征變為可枚舉,而默認情況下它是不可枚舉的,如果想不可枚舉,可以使用Object.defineProperty()方法。
原型的動態性對原型對象的修改會體現在實例對象上,即使實例對象先被創建。但是通過對象字面量重寫的原型對象則沒有該動態性
優點定義在原型對象上的屬性,能夠保證在各實例對象上的共享
缺點對于引用類型的屬性,各實例的共享會導致額外的問題。
組合使用構造函數模式與原型模式整合構造函數模式與原型模式,構造函數模式用于定義實例屬性,原型模式用于定義方法和共享屬性。
動態原型模式 寄生構造函數模式 穩妥構造函數模式 各創建模式在Chrome瀏覽器中的表現可以通過Chrome瀏覽器觀察使用工廠模式創建的cheesePizza對象屬性為:
cheesePizza {type: "cheese", bake: ?} bake: ? () type: "cheese" __proto__: constructor: ? Object() hasOwnProperty: ? hasOwnProperty() isPrototypeOf: ? isPrototypeOf() propertyIsEnumerable: ? propertyIsEnumerable() toLocaleString: ? toLocaleString() toString: ? toString() valueOf: ? valueOf() __defineGetter__: ? __defineGetter__() __defineSetter__: ? __defineSetter__() __lookupGetter__: ? __lookupGetter__() __lookupSetter__: ? __lookupSetter__() get __proto__: ? __proto__() set __proto__: ? __proto__()
使用構造函數模式創建cheesePizza對象屬性為:
cheesePizza Pizza {type: "cheese", bake: ?} bake: ? () type: "cheese" __proto__: constructor: ? Pizza(type) __proto__: constructor: ? Object() hasOwnProperty: ? hasOwnProperty() isPrototypeOf: ? isPrototypeOf() propertyIsEnumerable: ? propertyIsEnumerable() toLocaleString: ? toLocaleString() toString: ? toString() valueOf: ? valueOf() __defineGetter__: ? __defineGetter__() __defineSetter__: ? __defineSetter__() __lookupGetter__: ? __lookupGetter__() __lookupSetter__: ? __lookupSetter__() get __proto__: ? __proto__() set __proto__: ? __proto__()
使用原型模式創建cheesePizza對象屬性為:
cheesePizza Pizza {type: "cheese"} type: "cheese" __proto__: bake: ? () type: "original" constructor: ? Pizza() __proto__: constructor: ? Object() hasOwnProperty: ? hasOwnProperty() isPrototypeOf: ? isPrototypeOf() propertyIsEnumerable: ? propertyIsEnumerable() toLocaleString: ? toLocaleString() toString: ? toString() valueOf: ? valueOf() __defineGetter__: ? __defineGetter__() __defineSetter__: ? __defineSetter__() __lookupGetter__: ? __lookupGetter__() __lookupSetter__: ? __lookupSetter__() get __proto__: ? __proto__() set __proto__: ? __proto__()參考文章
ESLint 需要約束 for-in (guard-for-in)
個人不定期更新主頁
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100145.html
摘要:執行上下文作用域鏈和內部機制一執行上下文執行上下文是代碼的執行環境,它包括的值變量對象和函數。創建作用域鏈一旦可變對象創建完,引擎就開始初始化作用域鏈。 執行上下文、作用域鏈和JS內部機制(Execution context, Scope chain and JavaScript internals) 一、執行上下文 執行上下文(Execution context EC)是js代碼的執...
摘要:當這步完成,這個對象就與構造函數再無聯系,這個時候即使構造函數再加任何成員,都不再影響已經實例化的對象了。此時,對象具有了和屬性,同時具有了構造函數的原型對象的所有成員,當然,此時該原型對象是沒有成員的。 前言 本篇文章用來記錄下最近研究對象的一些心得,做一個記錄與總結,以加深自己的印象,同時,希望也能給正在學習中的你一點啟發。本文適合有一定JavaScript基礎的童鞋閱讀。原文戳這...
摘要:后端知識點總結基礎不是是一種軟件開發平臺,它的競爭對象歷史第一次有一種語言可以通吃前后端網站阿里云鏡像版本年初年中年底最新版本功能強大可靠,適合大型企業級項目簡單易用適合互聯網項目易用適合平臺性能好適合服務器端密集型項目不適合密集型項目密集 后端知識點總結——NODE.JS基礎 1.Node.js Node.js不是JS,是一種軟件開發平臺,它的競爭對象JSP/PHP/ASP.NET...
摘要:要用作原型的對象。函數對象可以創建普通對象,這個我們上面講過了回顧一下這是一個自定義構造函數普通對象沒法創建函數對象,凡是通過創建的對象都是函數對象,其他都是普通對象通常通過創建,可以通過來判斷。 關于js的原型和原型鏈,有人覺得這是很頭疼的一塊知識點,其實不然,它很基礎,不信,往下看要了解原型和原型鏈,我們得先從對象說起 創建對象 創建對象的三種方式: 對象直接量 通過對象直接量創建...
閱讀 2162·2021-10-08 10:15
閱讀 1193·2019-08-30 15:52
閱讀 521·2019-08-30 12:54
閱讀 1538·2019-08-29 15:10
閱讀 2691·2019-08-29 12:44
閱讀 3013·2019-08-29 12:28
閱讀 3357·2019-08-27 10:57
閱讀 2221·2019-08-26 12:24