摘要:理解對象創(chuàng)建方式函數(shù)生成和字面量例如構(gòu)造函數(shù)方式調(diào)用函數(shù)字面量屬性類型數(shù)據(jù)屬性能否修改屬性能否通過循環(huán)獲取能否修改通過方法修改默認(rèn)屬性例如值沒有改變訪問器屬性函數(shù)特性例如讀取創(chuàng)建對象工廠模式定義本義是將創(chuàng)建相同或相似對象的過程進(jìn)行封裝,只需
6.1理解對象
創(chuàng)建方式:函數(shù)生成 和 字面量
例如:
var a = new Object(); // new 構(gòu)造函數(shù)方式 var a = Object(); // 調(diào)用函數(shù) var a = {}; // 字面量屬性類型
(1)數(shù)據(jù)屬性:[[configurable]](能否修改屬性), [[enumerable]](能否通過for in 循環(huán)獲取),[[writable]](能否修改),[[value]], 通過Object.defineProperty(obj, proper, properObj)方法修改默認(rèn)屬性
例如:
var a = { name: "jiang" }; console.log(Object.getOwnPropertyDescriptor(a, "name")); // {value: "jiang", writable: true, enumerable: true, configurable: true} Object.defineProperty(a, "name", { "writable": false}); a.name = "zhong"; console.log(Object.getOwnPropertyDescriptor(a, "name")); // {value: "jiang", writable: false, enumerable: true, configurable: true} // 值沒有改變
(2)訪問器屬性:函數(shù)(getter(),setter), 特性([[Configuable]], [[Enumerable]], [[Get]], [[Set]])
例如:
var a = { name: "jiang" }; Object.defineProperty(a, "sex", { get: function(){ return 1; }, }); a.name = "zhong"; console.log(a); console.log(a.sex);
(3)讀取:Object.getOwnPropertyDescriptor()
6.2創(chuàng)建對象 工廠模式定義:本義是將創(chuàng)建相同或相似對象的過程進(jìn)行封裝,只需調(diào)用封裝后的函數(shù)就可以獲取對象
解決的問題:類似的對象不用寫重復(fù)的代碼
帶來的問題:創(chuàng)建的對象沒有類型標(biāo)識
function factory(name){ var o = {}; 0.name = name; o.action = function(){}; return o; };// 在這里factory就是工廠模式的工廠 var instance1 = facroty("san"); var instance2 = facroty("si");構(gòu)造函數(shù)
定義:形如:function A(){};的函數(shù), 通過new來進(jìn)行實例化
解決的問題:同一個構(gòu)造函數(shù)產(chǎn)生的實例類型項目(可以通過instanceOf鑒定), 實例間共享原型對象的屬性
特點:構(gòu)造函數(shù)內(nèi)部的this指的是當(dāng)前的實例對象
帶來的問題:每個方法都屬于不同的實例,就是沒創(chuàng)建一個實例方法就會重新創(chuàng)建一遍
function Factory(name){ this.name = name; this.action = function(){}; }; var instance1 = new Factory("san"); var instance2 = new Factory("si"); console.log(instance1 instanceof Factory); // true console.log(instance2 instanceof Factory); // true原型模式
定義:一個對象中屬性和方法被所有實例所共享(共享實例都可以看成是這個復(fù)制品),這樣的對象就是原型對象
解決的問題:構(gòu)造函數(shù)的方法和屬性在各個實例間是共享的
function Func(){}; Func.prototype.name = "xiaotu"; Func.prototype.action = function(){ console.log(this.name,"跑路"); }; var instance1 = new Func(); var instance2 = new Func(); instance1.action(); // xiaotu 跑路 instance2.action(); // xiaotu 跑路
特點:(1)通過new 構(gòu)造函數(shù)產(chǎn)生實例對象,構(gòu)造函數(shù)默認(rèn)屬性prototype指向?qū)嵗龑ο蟮脑蛯ο螅?原型對象的默認(rèn)的constructor(constructor屬性被實例對象所共享)屬性又指向構(gòu)造函數(shù), 實例對象通過[[ProtoType]]指向?qū)嵗迷蛯ο?/p>
function Func(){}; console.log(Func.prototype); // {constructor: ?} console.log(Func.prototype.constructor); // ? Func(){} var instance1 = new Func(); // instance1可以訪問原型的constructor console.log(instance1.constructor) // ? Func(){} console.log(instance1.__proto__) // {constructor: ?} // 關(guān)系圖(*代表指向目標(biāo)) constructor *---------------------------- 函數(shù)(Func) ----------------------* 原型對象(Func.prototype) (prototype) * / (new) (_proto_)/(Object.getPrototypeOf(instance1)) / / / / / 對象實例(instance1)
(2)實例對象與原型對象之間的對應(yīng)關(guān)系可以通過isProtoTypeOf()來判斷, 可以通過getProtoTypeOf()獲取對象實例的原型對象
function Func(){}; var instance1 = new Func(); console.log(Func.prototype.isPrototypeOf(instance1)); // true console.log(Object.getPrototypeOf(instance1)); // {constructor: ?}
(3)實例對象與原型對象的屬性可以重復(fù)但不會覆蓋,只是搜索時優(yōu)先搜索實例對象的
function Func(){ this.name = "jiang"; }; Func.prototype.name = "zhong"; var instance1 = new Func(); console.log(instance1.name); // jiang delete instance1.name; console.log(instance1.name); // zhong
(4)hasProprtyOf():判斷對象實例中是否有此屬性, in:判斷對象實例和原型對象中是否由此屬性, for - in 循環(huán)遍歷包括原型和實例的屬性, Object.keys() 返回所有實例的屬性
function Func(){ }; Func.prototype.name = "zhong"; var instance1 = new Func(); console.log(instance1.hasOwnProperty("name")); // false console.log("name" in instance1); // true
(5)原型對象添加屬性的方式:"."(增量添加) "{}"(覆蓋添加此時有默認(rèn)的constructor指向Object)
帶來的問題:如果原型對象的屬性是引用類型的那么實例對象和原型對象的這個屬性是同一個引用, 所以有了組合原型模式和構(gòu)造函數(shù),將引用屬性定義在構(gòu)造中就沒這個問題了
注:當(dāng)通過實例去寫值得時候如果實例不存在該屬性則會去原型屬性中查找,如果在原型中是引用類型的屬性則對原型屬性修改,如果是基本類型的則在實例中新建屬性并賦值
function Func(){ this.legs = ["left"]; }; Func.prototype.arms = ["right"]; var instance1 = new Func(); instance1.legs.push("right"); instance1.arms.push("left"); var instance2 = new Func(); console.log(instance2.legs); // ["left"] console.log(instance2.arms); // ["right", "left"] console.log(instance2.hasOwnProperty("arms")); // false console.log(instance2.__proto__.hasOwnProperty("arms")); // true組合原型模式和構(gòu)造函數(shù):原型模式負(fù)責(zé)定義實例共享的屬性和方法, 構(gòu)造函數(shù)定義每個實例特定的方法和屬性
如上例(5)6.3繼承
只支持實現(xiàn)繼承(相對于接口繼承)原型鏈
定義:將一個(函數(shù)A)對象實例a賦值給某個函數(shù)B的原型B.prototype,那么B的實例b就擁有了a的屬性,如果讓A的原型的值等于另一個實例,a也擁有了其他對象的值, 如此形成了原型鏈 解決的問題:讓對象之間實現(xiàn)了繼承
function SuperFunc(){ this.name = "big-jiang"; }; function SubFunc(){ this.name = "small-jiang"; }; var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; var subFunc = new SubFunc(); console.log(subFunc.name); // "small-jiang" console.log(subFunc.__proto__.name); // "big-jiang" SuperFunc.prototype = new ... // 繼續(xù)繼承成鏈
特點: (1)所有對象都繼承了Object, 可以通過對象原型的原型(最后一層原型)的constructor是否指向Object的原型去判斷
function SuperFunc(){ this.name = "big-jiang"; }; function SubFunc(){ this.name = "small-jiang"; }; console.log(SuperFunc.prototype.constructor == Object); // false 應(yīng)是SuperFunc console.log(SuperFunc.prototype.__proto__.constructor == Object); // true var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; console.log(SubFunc.prototype.constructor == SubFunc); // false 應(yīng)是SuperFunc console.log(SubFunc.prototype.constructor == SuperFunc); // true console.log(SubFunc.prototype.__proto__.constructor == SuperFunc); // true console.log(SubFunc.prototype.__proto__.__proto__.constructor == Object); // true
(2)確定某原型是不是對應(yīng)某實例間可以通過instanceOf和isPrototypeOf()
function SuperFunc(){ this.name = "big-jiang"; }; function SubFunc(){ this.name = "small-jiang"; }; var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; var subFunc = new SubFunc(); console.log(subFunc instanceof SubFunc); // true console.log(subFunc instanceof SuperFunc); // true
帶來的問題:父級的實例變成了子級的原型,父級的屬性是引用類型的話就會帶來所有實例共享的問題,不能向父級構(gòu)造函數(shù)傳遞參數(shù)
function SuperFunc(){ this.arms = ["left"]; }; function SubFunc(){ }; var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; var subFunc1 = new SubFunc(); subFunc1.arms.push("right"); var subFunc2 = new SubFunc(); console.log(subFunc2.arms); // ["left", "right"]借用構(gòu)造函數(shù)
定義:在子函數(shù)中通過apply或者call將當(dāng)前作用域傳給父函數(shù)來實現(xiàn)繼承 解決的問題:這樣就不會有原型帶來的共享引用屬性的問題, 也可以在apply或者call中傳遞參數(shù)
function SuperFunc(name){ this.name = name; }; function SubFunc(){ this.name = "zhong"; SuperFunc.call(this, "jiang"); }; var subFunc = new SubFunc(); console.log(subFunc.name); // jiang
帶來的問題:復(fù)用性差,父級原型中的屬性方法,自己都不能獲取到組合繼承
定義:將借用構(gòu)造函數(shù)和作用域鏈兩種方式結(jié)合起來使用 解決的問題:將前兩種繼承方式的優(yōu)點結(jié)合起來, 缺點可以選擇性去避免
function SuperFunc(name){ this.name = name; this.arms = ["left"]; }; function SubFunc(){ SuperFunc.call(this, "jiang"); }; var superFunc = new SuperFunc(); SubFunc.prototype = superFunc; var subFunc = new SubFunc(); subFunc.arms.push("right"); var subFunc2 = new SubFunc(); console.log(subFunc2.arms); // "left"
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/100487.html
摘要:對象數(shù)組初始化表達(dá)式,闖關(guān)記之上文檔對象模型是針對和文檔的一個。闖關(guān)記之?dāng)?shù)組數(shù)組是值的有序集合。數(shù)組是動態(tài)的,根闖關(guān)記之語法的語法大量借鑒了及其他類語言如和的語法。 《JavaScript 闖關(guān)記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素...
摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強(qiáng)大。中文指南基本操作指南二繼續(xù)熟悉的幾對方法,包括,,。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...
摘要:對象在中,除了數(shù)字字符串布爾值這幾個簡單類型外,其他的都是對象。那么在函數(shù)對象中,這兩個屬性的有什么區(qū)別呢表示該函數(shù)對象的原型表示使用來執(zhí)行該函數(shù)時這種函數(shù)一般成為構(gòu)造函數(shù),后面會講解,新創(chuàng)建的對象的原型。這時的函數(shù)通常稱為構(gòu)造函數(shù)。。 本文原發(fā)于我的個人博客,經(jīng)多次修改后發(fā)到sf上。本文仍在不斷修改中,最新版請訪問個人博客。 最近工作一直在用nodejs做開發(fā),有了nodejs,...
摘要:然后將構(gòu)造函數(shù)的原型設(shè)為,便實現(xiàn)了對象繼承。首先,我們定義一個構(gòu)造函數(shù),并在其中定義一個局部變量。這里的是局部變量,其作用域仍然存在是閉包現(xiàn)象,而非對象屬性。 Javascript是動態(tài)的,弱類型的,解釋執(zhí)行的程序設(shè)計語言。 Javascript極其靈活,支持多種程序設(shè)計范式:面向?qū)ο?、指令式、函?shù)式。JavaSCript最初被用于瀏覽器腳本,現(xiàn)在已經(jīng)是所有主流瀏覽器的默認(rèn)腳本語言。瀏...
摘要:可嵌入動態(tài)文本于頁面,對瀏覽器事件作出響應(yīng),讀寫元素,控制等。年月,發(fā)布了一款面向普通用戶的新一代的瀏覽器版,市場份額一舉超過。網(wǎng)景將這門語言作為標(biāo)準(zhǔn)提交給了歐洲計算機(jī)制造協(xié)會。線程和的并發(fā)執(zhí)行都是線程安全的。后面會詳細(xì)講解對象類型的轉(zhuǎn)換。 本文由云+社區(qū)發(fā)表作者:殷源,專注移動客戶端開發(fā),微軟Imagine Cup中國區(qū)特等獎獲得者 JavaScript越來越多地出現(xiàn)在我們客戶端開...
摘要:在中,并沒有對抽象類和接口的支持。例如,當(dāng)對象需要對象的能力時,可以有選擇地把對象的構(gòu)造器的原型指向?qū)ο?,從而達(dá)到繼承的效果。本節(jié)內(nèi)容為設(shè)計模式與開發(fā)實踐第一章筆記。 動態(tài)類型語言 編程語言按數(shù)據(jù)類型大體可以分為兩類:靜態(tài)類型語言與動態(tài)類型語言。 靜態(tài)類型語言在編譯時已確定變量類型,動態(tài)類型語言的變量類型要到程序運行時,待變量被賦值后,才具有某種類型。 而JavaScript是一門典型...
閱讀 607·2021-11-18 13:12
閱讀 1324·2021-11-15 11:39
閱讀 2487·2021-09-23 11:22
閱讀 6221·2021-09-22 15:15
閱讀 3668·2021-09-02 09:54
閱讀 2320·2019-08-30 11:10
閱讀 3252·2019-08-29 14:13
閱讀 2918·2019-08-29 12:49