摘要:中創(chuàng)建對象是如何實現(xiàn)的其實通過上面方式,使用構造函數(shù)聲明實例的專屬變量和方法,使用原型聲明公用的實例和方法,已經(jīng)是創(chuàng)建對象的完美解決方案了。
var cat = { name: "tom", info: this.name + ": 1212", getName: function() { return this.name; } };
注意上例屬性info中,使用了this.name,這里的this指向window對象,請盡量避免在定義對象屬性時使用表達式,而將有表達式的內(nèi)容寫入到函數(shù)中。
var dog = new Object(); dog.name = "tim"; dog.getName = function() { return dog.name; }
可以使用delete刪除對象的屬性和方法
delete dog.name;
在window作用域中,不能使用delete刪除var, function定義的屬性和方法,可以刪除沒有使用var, function定義的屬性和方法
在實際使用當中,字面量創(chuàng)建對象雖然很有用,但是它并不能滿足我們的所有需求,我們希望能夠能夠和其他后臺語言一樣創(chuàng)建一個類,然后聲明類的實例就能夠多次使用,而不用每次使用的時候都要重新創(chuàng)建它,于是,便有了工廠模式的出現(xiàn)。
function person(name) { var o = new Object(); o.name = name; o.getName = function() { return this.name; } return o; } var person1 = person("rose"); var person2 = person("jake");
這種模式在函數(shù)的內(nèi)部創(chuàng)建了一個空對象,然后逐一添加屬性和方法,最后返回,實現(xiàn)了對象得以復用的目的。但是存在2個很大的問題
無法識別對象的類型
console.log(person1 instanceof person); // false
每個對象調(diào)用的同名方法其實并不同一個方法
console.log(person1.getName == person2.getName); // false
其實就相當于每次聲明對象都被重新創(chuàng)建,只不過寫法上簡單了一點而已。
var Person = function(name) { this.name = name; this.getName = function() { return this.name; } } var person1 = new Person("tom"); var person2 = new Person("tim");
使用var或者function聲明函數(shù)都可以,只是我寫例子的時候想到什么就寫了什么,這個區(qū)別在這里不是重點
和工廠模式相比,自定義構造函數(shù)沒有在函數(shù)內(nèi)部顯示的創(chuàng)建和返回對象,而是使用this,當然,看上去簡潔了許多,那么它解決了工廠模式的什么問題呢?
console.log(person1 instanceof Person); // ture console.log(person1.getName == person2.getName); //false
從上面代碼可以看出,對象的類別可以判斷了,person1就是Person的對象,可是2個同名方法任然不是同一個方法,而是重新創(chuàng)建,其實構造函數(shù)內(nèi)部的實現(xiàn),可以將上面的代碼寫成這樣來理解
var Person = function(name) { var this = {}; this.name = name; this.getName = function() { return this.name; } return this; }
看上去和工廠模式就有點像,只是this的聲明和返回都是隱式的。下一步,我們將要介紹關鍵先生,原型
原型并沒有那么神秘,因為在javascript中,它無處不在。為了了解原型,我們可以在chrome瀏覽器的console中,隨意創(chuàng)建一個函數(shù)
function a(){}
然后繼續(xù)輸入
a.prototype
得到的結果如下
a { constructor: function a(), _proto_: Object }
沒錯,得到的這個a,就是關鍵先生原型了。每一個函數(shù)都有一個prototype屬性,他就像一個指針一樣指向它的原型,而每一個原型,都有一個constructor屬性,指向他的構造函數(shù)。
那么原型在創(chuàng)建對象中有什么用呢?
一個例子,千錘百煉,如下
function Person(name) { this.name = name; } Person.prototype.getName = function() { return this.name; } var person1 = new Person("rose"); var person2 = new Person("Jake");
在這里,我們將屬性寫在了構造函數(shù)里,將令人頭疼的方法寫在原型里,看看上面的問題得到解決沒有
console.log(person1 instanceof Person); // true console.log(person1.getName === person2.getName); // true
OK,問題完美解決。
當然也可以將屬性寫入原型中,但是如果那樣的話,屬性就會如同方法一樣被公用了,因此一般來說,屬性會寫入構造函數(shù)之中,方法寫入原型之中。當然,這視情況而定。
如果你想進一步了解原型,可以看下圖。
當我們使用new Person時便會創(chuàng)建一個實例,比如這里的person1與person2,這里的實例中,會有一個_proto_屬性指向原型。
原型中的查找機制
當我們使用實例person1調(diào)用方法person.getName()時,我們首先找的,是看看構造函數(shù)里面有沒有這個方法,如果構造函數(shù)中存在,就直接調(diào)用構造函數(shù)的方法,如果構造函數(shù)不存在,才回去查找原型中是否存在該方法
function Cat(name) { this.name = name; this.age = 12; this.getName = function() { return "constructor"; } } Cat.prototype.name = "proto name"; Cat.prototype.getName = function() { return this.name; } var tim = new Cat("Tim"); console.log(tim.name); // tim console.log(tim.getName()); // constructor
可以看到上例中,當原型和構造函數(shù)中擁有同樣的方法和屬性的時候,構造函數(shù)中的被執(zhí)行。
于是,這里便會有一個十分重要的概念需要理解,那就是this的指向問題。
在整個創(chuàng)建對象的過程當中,this到底指向誰?
function Person(name) { this.name = name; // this.getName = function() { // return "constructor"; // } } Person.prototype.getName = function() { return this.name; } Person.prototype.showName = function() { return this.getName(); } var rose = new Person("rose"); console.log(rose.showName()); //rose
其實在new執(zhí)行時,構造函數(shù)中的this與原型中的this都被強行指向了new創(chuàng)建的實例對象。
如果需要寫在原型上的方法很多的話,還可以這樣來寫,讓寫法看上去更加簡潔
Person.prototype = { constructor: Person, getName: function(){}, showName: function(){}, ... }
constructor:Person這一句必不可少,因為{}也是一個對象,當使用Person.prototype = {}時,相當于重新定義了prototype的指向,因此手動修正{}的constructor屬性,讓他成為Person的原型。
其實通過上面方式,使用構造函數(shù)聲明實例的專屬變量和方法,使用原型聲明公用的實例和方法,已經(jīng)是創(chuàng)建對象的完美解決方案了。可是唯一的不足在于,每次創(chuàng)建實例都要使用new來聲明。這樣未免太過麻煩,如果jquery對象也這樣創(chuàng)建,那么你就會看到一段代碼中有無數(shù)個new,可是jQuery僅僅只是使用了$("xxxx")便完成了實例的創(chuàng)建,這是如何做到的呢?
還是按照慣例,先貼代碼。
(function(window, undefined) { var Person = function(name) { return new Person.fn.init(name); } Person.prototype = Person.fn = { constructor: Person, init: function(name) { this.name = name; return this; }, getName: function() { return this.name; } } Person.fn.init.prototype = Person.fn; window.Person = window.$ = Person; })(window); console.log($("tom").getName());
一步一步來分析
首先為了避免變量污染,使用了函數(shù)自執(zhí)行的方式。這種方式讓javascript代碼具備了模塊的特性,因此大多數(shù)js庫都會這樣做
(function(){ ... })()
傳入window參數(shù),是為了讓jquery對象在外window中可以被訪問,因此有如下一句代碼
window.Person = window.$ = Person;
這樣我們就可以直接使用$來調(diào)用Person構造函數(shù)
關鍵問題在于,真正的構造函數(shù)并不是Person,而是Person原型中的init方法。其中的復雜關系,我們借助下圖來分析了解,表達能力實在有限,也不知道如何才能表達的更加簡潔易懂。
當外部調(diào)用$().getName()時,函數(shù)內(nèi)部的執(zhí)行順序如下
new Person.fn.init() // 而init的原型,通過下面一句指向了Person的原型 Person.fn.init.prototype = Person.fn; // 于是就可以調(diào)用原型中的getName方法了
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/86189.html
摘要:字面量方式這是最簡單最基本的一種方法。簡單的構造函數(shù)方式通過這樣的形式創(chuàng)建對象。結合上面的簡單構造函數(shù)和原型,一個完整的構造函數(shù)應該是這樣的還有一種方法就是提供的簡單實現(xiàn)下中的,,創(chuàng)建一個對象談談對象的理解。避免使用表達式又稱動態(tài)屬性。 要點:數(shù)據(jù)類型、面向?qū)ο蟆⒗^承、閉包、插件、作用域、跨域、原型鏈、模塊化、自定義事件、異步裝載回調(diào)、模板引擎、Nodejs等。 JS基本類型有什么?引...
摘要:接下來該填表了生成行和單元格為了填充表格可以遵循同樣的方法,但這次我們需要迭代數(shù)組中的每個對象。對于每個對象,我們可以使用生成單元格。 翻譯:瘋狂的技術宅原文:https://www.valentinog.com/bl... 本文首發(fā)微信公眾號:jingchengyideng歡迎關注,每天都給你推送新鮮的前端技術文章 怎樣用原生 JavaScript 生成表格需?本文告訴你答案!...
摘要:在中函數(shù)是一等對象,它們不被聲明為任何東西的一部分,而所引用的對象稱為函數(shù)上下文并不是由聲明函數(shù)的方式?jīng)Q定的,而是由調(diào)用函數(shù)的方式?jīng)Q定的。更為準確的表述應該為當對象充當函數(shù)的調(diào)用函數(shù)上下文時,函數(shù)就充當了對象的方法。 引言:當理解了對象和函數(shù)的基本概念,你可能會發(fā)現(xiàn),在JavaScript中有很多原以為理所當然(或盲目接受)的事情開始變得更有意義了。 1.JavaScript...
摘要:點擊直達前文譯一個小時搭建一個全棧應用框架上如果沒有,但還是要繼續(xù)學習本教程,可以到我的頁面下載代碼。從服務器返回隨機語言的每當我們與服務器上的端點進行通話時,為了能夠請求一個隨機的歐洲語言,必須更改文件中的功能。 翻譯:瘋狂的技術宅原文標題:Creating a full-stack web application with Python, NPM, Webpack and Reac...
摘要:點擊直達前文譯一個小時搭建一個全棧應用框架上如果沒有,但還是要繼續(xù)學習本教程,可以到我的頁面下載代碼。從服務器返回隨機語言的每當我們與服務器上的端點進行通話時,為了能夠請求一個隨機的歐洲語言,必須更改文件中的功能。 翻譯:瘋狂的技術宅原文標題:Creating a full-stack web application with Python, NPM, Webpack and Reac...
閱讀 2022·2021-09-29 09:35
閱讀 1955·2019-08-30 14:15
閱讀 2980·2019-08-30 10:56
閱讀 964·2019-08-29 16:59
閱讀 577·2019-08-29 14:04
閱讀 1310·2019-08-29 12:30
閱讀 1031·2019-08-28 18:19
閱讀 515·2019-08-26 11:51