摘要:簡單方式創建對象字面量方式創建對象方式創建對象雖然構造函數或對象字面量都可以用來創建單個對象,但這些方式有個明顯的缺點使用同一個接口創建很多對象,會產生大量的重復代碼,如上面的代碼,每創建一個類似的對象,就會重復上面的寫法,代碼較為冗余為了
1. 簡單方式創建對象
// 字面量方式創建對象 var person1 = { name: "xyc", age: 23, sayHi: function() { console.log(name); } }; // Object方式創建對象 var person2 = new Object(); person2.name = "lxy"; person2.age = 18; person2.sayHi = function() { console.log(person2.name); }
雖然Object構造函數或對象字面量都可以用來創建單個對象,但這些方式有個明顯的缺點:使用同一個接口創建很多對象,會產生大量的重復代碼,如上面的代碼,每創建一個類似的person對象,就會重復上面的寫法,代碼較為冗余
為了解決這個問題(代碼重復),下面引入工廠模式 ==>
2. 工廠模式創建對象function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var person1 = createPerson("Nicholas", 29, "Software Engineer"); var person2 = createPerson("Greg", 27, "Doctor");
通俗的解釋:工廠模式就是利用了函數的封裝調用,類比工廠材料==>成品的過程,完成入口參數==>對象的過程,函數可以無數次的生成,因此能夠避免上面產生大量重復代碼的情況。工廠模式雖然解決了創建多個相似對象的問題,但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)
為解決這個問題(對象識別),下面引入構造函數模式
3. 構造函數創建對象 3.1 構造函數與普通函數的區別命名規則:構造函數一般是首字母大寫,普通函數遵照小駝峰式命名法
函數調用:
構造函數:
(1)new fn( )
(2)構造函數內部會創建一個新的對象,即f的實例
(3)函數內部的this指向 新創建的f的實例
(4)默認的返回值是f的實例
普通函數:
(1)fn( )
(2)在調用函數的內部不會創建新的對象
(3)函數內部的this指向調用函數的對象(如果沒有對象調用,默認是window)
(4)返回值由return語句決定
構造函數的返回值:
有一個默認的返回值,新創建的對象(實例),當手動添加返回值后(return語句):
(1)返回值是基本數據類型-->真正的返回值還是那個新創建的對象(實例)
(2)返回值是復雜數據類型(對象)-->真正的返回值是這個對象
function foo() { var f2 = new foo2(); console.log(f2); // {a: 3} console.log(this); // window return true; } function foo2() { console.log(this); // foo2類型的對象 不是foo2函數 return {a: 3}; } var f1 = foo(); console.log(f1); // true3.2 new 操作符作用
使用new操作符調用構造函數會經歷下面幾個步驟:
(1)創建一個以這個函數為原型的空對象.
(2)將函數的 prototype 賦值給對象的 proto 屬性
(3)將對象作為函數的 this 傳進去。如果有 return 出來東西是對象的話就直接返回 return 的內容,沒有的話就返回創建的這個對象
function NewFunc(func){ var ret = {}; if (func.prototype !== null) { ret.__proto__ = func.prototype; } var ret1 = func.apply(ret, Array.prototype.slice.call(arguments, 1)); if ((typeof ret1 === "object" || typeof ret1 === "function") && ret1 !== null) { return ret1; } return ret; }
普通函數的作用主要是封裝作用,能夠在作用域內多處調用而已
3.3 構造函數解決對象識別創建自定義的構造函數意味著可以通過 instanceof 將它的實例標識為一種特定的類型
function Person(name,age,job){ this.name = name; this.age = age; this.sayHi = function(){ console.log(this.name); } } var person1 = new Person("xyc", 23); var person2 = new Person("lxy", 22); console.log(person1 instanceof Person); //true console.log(person2 instanceof Person); //true console.log(person1 instanceof Object); //true 因為Person繼承自Object,所以這里一樣成立.3.4 缺陷
構造函數創建對象的方式解決了代碼重復和對象識別的問題,但是創建的對象中含有方法時,每實例化一個Person,就會產生一個方法,也就是一個對象,每個對象分別占據內存。因此,構造函數創建對象的方式存在內存大量占用的風險
利用原型共享的特性,下面引入原型模式
4. 原型創建對象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.sayName(); //"Nicholas" person2.sayName(); //"Nicholas" person1.friends.push("Van"); alert(person1.friends); //"Shelby,Court,Van" alert(person2.friends); //"Shelby,Court,Van" alert(person1.friends === person2.friends); //true
原型創建對象的方式將屬性和方法都存在與原型中,也就是說,只要通過這種形式創建的對象都會共享這些屬性和對象,相對于方法共享這是我們樂于看到的,但是屬性共享讓每個實例缺失了“個性”;另外對于引用類型的屬性共享時,如上面的例子,多個實例對引用類型的操作會被篡改。
實例一般都要有屬于自己的全部屬性,這也決定了原型創建方式的局限性。下面引入非常經典的對象創建方式
5. 構造函數+原型創建對象(重點)組合構造函數模式與原型模式:構造函數模式用于定義實力屬性,而原型模式用于定義方法和共享的屬性
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"]; } Person.prototype = { constructor : Person, sayName : function(){ alert(this.name); } } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1.friends.push("Van"); alert(person1.friends); //"Shelby,Count,Van" alert(person2.friends); //"Shelby,Count" alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true
這種方式創建的實例對象,每個實例都會有自己的一份實例屬性的副本,但同時又共享著對方法的引用,最大限度地節省了內存;另外,這種方式還支持相構造函數傳遞參數,解決了上面的各種問題
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89476.html
摘要:因此,所有在方法中定義的變量都是放在棧內存中的當我們在程序中創建一個對象時,這個對象將被保存到運行時數據區中,以便反復利用因為對象的創建成本通常較大,這個運行時數據區就是堆內存。 上一篇:《javascript高級程序設計》筆記:繼承近幾篇博客都會圍繞著圖中的知識點展開 showImg(https://segmentfault.com/img/bVY0C4?w=1330&h=618);...
摘要:上一篇你不知道的筆記寫在前面這是年第一篇博客,回顧去年年初列的學習清單,發現僅有部分完成了。當然,這并不影響年是向上的一年在新的城市穩定連續堅持健身三個月早睡早起游戲時間大大縮減,學會生活。 上一篇:《你不知道的javascript》筆記_this 寫在前面 這是2019年第一篇博客,回顧去年年初列的學習清單,發現僅有部分完成了。當然,這并不影響2018年是向上的一年:在新的城市穩定、...
摘要:繼承和前面兩篇文章中的知識非常相關,如果對函數創建原理和原型鏈不熟悉,請猛戳高級程序設計筆記創建對象高級程序設計筆記原型圖解繼承,通俗的說,就是將自身不存在的屬性或方法,通過某種方式為自己所用文章分別介紹原型鏈繼承繼承借用構造函數繼承組合繼 繼承和前面兩篇文章中的知識非常相關,如果對函數創建原理和原型鏈不熟悉,請猛戳:《javascript高級程序設計》筆記:創建對象《javascri...
摘要:如果重設構造函數的原型對象,那么,會切斷新的原型對象和任何之前已經存在的構造函數實例之間的聯系,它們引用的仍然是最初的原型。說明返回的對象與構造函數或者與構造函數的原型屬性沒有關系。 說明: 此摘要筆記系列是我最近看《JavaScript高級程序設計(第3版)》隨手所記。里面分條列舉了一些我認為重要的、需要記下的、對我有幫助的點,是按照我看的順序來的。摘要筆記本身沒有系統性,沒有全面性...
摘要:繼承傳統的面向對象語言,繼承是類與類之間的關系。原型繼承原型定義原型就是指構造函數的屬性所引用的對象。創建構造函數創建的實例對象張三李四就是對象的原型也是的原型在原型上創建一個屬性運行和,并對比是否為同一個方法。 原文鏈接:http://www.hansmkiii.com/2018/07/06/javascript-node-1/ 面向對象、原型、繼承 1、面向對象 1.1 什么...
摘要:檢查當前上下文中的參數,建立該對象下的屬性與屬性值。檢查當前上下文的函數聲明,也就是使用關鍵字聲明的函數。如果該變量名的屬性已經存在,為了防止同名的函數被修改為,則會直接跳過,原屬性值不會被修改。 上一篇:《javascript高級程序設計》筆記:內存與執行環境showImg(https://segmentfault.com/img/bVY4xr?w=1146&h=374); 上篇文章...
閱讀 2568·2023-04-25 17:33
閱讀 648·2021-11-23 09:51
閱讀 2951·2021-07-30 15:32
閱讀 1398·2019-08-29 18:40
閱讀 1940·2019-08-28 18:19
閱讀 1465·2019-08-26 13:48
閱讀 2237·2019-08-23 16:48
閱讀 2275·2019-08-23 15:56