摘要:中的首先,是一個操作符,它可以用來創(chuàng)建兩種對象的實例,一種是用戶定義的對象類型,另一種則是擁有構(gòu)造函數(shù)的內(nèi)建對象類型。這就是原型繼承構(gòu)造函數(shù)被調(diào)用并傳入指定的參數(shù)示例二中的,然后被綁定給新創(chuàng)建的對象。
JavaScript 中的 new
首先,new 是一個操作符,它可以用來創(chuàng)建兩種對象的實例,一種是用戶定義的對象類型,另一種則是擁有構(gòu)造函數(shù)的內(nèi)建對象類型。
創(chuàng)建用戶定義的對象需要兩個步驟:
通過編寫函數(shù)來定義對象類型;
使用 new 來創(chuàng)建對象實例。
示例一:
var Person = function(personName) { this.name = personName; };
這是一個典型的通過編寫函數(shù)來定義對象類型的范例,我們可以這樣來表述其行為:
Person 函數(shù)定義了一種對象類型,其 類型名稱 就叫 Person。
在使用 Person 函數(shù)創(chuàng)建對象實例的時候可以傳入變量 personName,該變量會成為對象實例的一個屬性,這個屬性的名字叫 name。
為對象實例定義 name 屬性的過程發(fā)生在 Person 函數(shù)的函數(shù)體內(nèi);this 即指代將被創(chuàng)建的對象實例。
值得初學者注意的是,在現(xiàn)實中你更多地會看到這樣的代碼:
var Person = function(name) { this.name = name; };
有些人會搞不清楚究竟哪一個 name 才是對象的屬性,在這里詳細解釋如下:
function(name) 里的 name 是待傳入?yún)?shù)的名字,通常被稱作:形式參數(shù)(Formal Parameter),或簡稱 形參 ——因為它只是代表參數(shù)的形式而并非真正傳入的參數(shù)(后者則被稱作:實際參數(shù)(Actual Parameter),或簡稱 實參)。
this.name 的 name 是對象的屬性名字。
= name 的 name 還是形參,和 1. 里的 name 等價;這就是所謂的 參數(shù)傳遞,或傳參。
示例二:
var albert = new Person("Albert"); albert.name; // "Albert" albert["name"]; // "Albert"
這是承接示例一,使用定義好的 Person 對象類型來實例化對象的范例,這個范例的表述相對容易一些:
定義一個變量 albert,然后實例化一個新的 Person 類型的對象,并將變量 albert 指向這個新的對象。
如果你對 形參 和 實參 還不夠清楚的話,看到這里就應(yīng)該完全明了了。保險起見再加以解釋如下:
在示例二中,new Person("Albert") 中的 "Albert" 即對應(yīng)著示例一中 function(name) 中的 name,同時也是接下來一行中等號右邊的 name。
因此,"Albert" 就是 實際參數(shù),name 就是 形式參數(shù)。
示例二中還演示了兩種對象屬性的獲取方法,分別為 object.property 和 object["property"]。前一種比較常用,不過后一種由于可以用字符串來訪問對象屬性,因此在某些場合下非常有用(比如說用字符串傳遞了對象的屬性)。
回到 new 的話題。
當 new Person("Albert") 執(zhí)行的時候,會有如下事情發(fā)生:
創(chuàng)建一個新的對象,其類型是 Person 并繼承 Person.prototype 的所有屬性。這就是 原型繼承;
構(gòu)造函數(shù) Person 被調(diào)用并傳入指定的參數(shù)(示例二中的 "Albert"),然后 this 被綁定給新創(chuàng)建的對象。另外,若構(gòu)造函數(shù)不需要參數(shù),則 new Person 等價于 new Person();
若構(gòu)造函數(shù)沒有明確的返回值,那么新創(chuàng)建的對象就是整個 new 表達式的結(jié)果;反之,若構(gòu)造函數(shù)內(nèi)顯式定義了返回值,則該返回值為整個 new 表達式的結(jié)果。
關(guān)于第三點,舉例示之:
示例三:
var Person = function(name) { return { name: "Mr. " + name } }; var albert = new Person("Albert"); albert.name; // "Mr. Albert"
var Person = function(name) { return { rawName: name, getName: function(gender) { if (gender === "male") { return "Mr. " + name; } else { return "Mrs. " + name; } } } }; var albert = new Person("Albert"); albert.getName("male"); // "Mr. Albert" albert.getName("female"); // "Mrs. Albert"
var Person = function(name, gender) { return { rawName: name, name: (function() { if (gender === "male") { return "Mr. " + name; } else { return "Mrs. " + name; } }()) } }; var albert = new Person("Albert", "male"); albert.rawName; // "Albert" albert.name; // "Mr. Albert" var annie = new Person("Annie", "female"); annie.rawName; // "Annie" annie.name; // "Mrs. Annie"
示例三演示了三種看起來相似但實際上具有顯著差異的對象類型定義和對象實例化的例子:
第一種:在 new Person("Albert") 時返回自定義的對象,而不是默認由 new 創(chuàng)建的新對象。在這個自定義對象里,沒有簡單地把參數(shù) name 賦給屬性 this.name,而是做了進一步的修改。這種修改很顯然是非常簡單但卻不夠靈活,為了改進它,看下面兩個例子:
第二種:同樣返回自定義對象,這一次定義了兩個屬性,一個是 rawName,保存實例化時傳遞的參數(shù);另一個是 getName,它是一個函數(shù)聲明,因此不能直接用 albert.getName 或 albert["getName"] 來訪問(只會返回函數(shù)聲明本身,但不會有返回值)。不過你可以用albert.getNam("male") 或 albert["getName"]("male") 的方式來執(zhí)行這個函數(shù)并求得結(jié)果,這就是所謂的 方法。
如果不想用方法調(diào)用,但仍然希望像方法聲明體內(nèi)那樣做一些邏輯判斷是否可以呢?可以,繼續(xù)看第三種:
第三種:這一次 name 屬性又可以像以前那樣直接訪問了,原因是 name 指向的函數(shù)聲明使用了 IIFE(Immediately Invoked Function Expression) 技巧,該技巧使得函數(shù)聲明直接轉(zhuǎn)變成了函數(shù)表達式(并即刻執(zhí)行)。我們知道,函數(shù)表達式是能夠直接返回值的,而函數(shù)聲明則需要執(zhí)行(調(diào)用)才能返回值,于是 name 屬性獲得了返回值,就可以像原來那樣直接訪問了。
這種屬性定義方式有時被稱之為 計算后屬性(Computed Property),顧名思義:不是直接返回實例化時傳遞的值,而是對值進行了一定的處理(計算)之后才返回。
屬性與方法:很多人都以為對象有 屬性 和 方法,其中屬性是可以直接訪問到值的,而方法是需要執(zhí)行才能獲得值的。但有的時候也會聽到“方法也是屬性”這樣的說法,這是為什么呢?
其實原因在于對術(shù)語的翻譯不夠準確。英文里的 property 和 attribute 都被我們翻譯為屬性,然而在談及對象時這兩者是不同的。在一個對象里,attribute 和 method 被統(tǒng)稱為 property,直接保存值的 property 稱之為 attribute,保存函數(shù)聲明可以用來執(zhí)行的 property 才是 method。在用中文描述時很容易把兩種“屬性”搞混,需要注意分辨清楚。
補充說明:本文發(fā)表出去之后,有人感謝我?guī)退智辶?屬性 和 方法 在一些書中的歧義性,也有人拿著別的書來向我表示疑惑。以再版的 Object Oriented in JavaScript 為例,該書中在講解面向?qū)ο蠡A(chǔ)的時候,明確地指出:保存數(shù)據(jù)的屬性叫做 Property,保存行為的屬性叫做 Method,根本就不使用 Attribute。這倒是也簡單明了,這樣一來就不存在 Method 也是 Property 一說了。
老實說,對此我也不知該如何回應(yīng)。不同的書用不同的術(shù)語,不同的作者也有不同的理解,我沒有“統(tǒng)一業(yè)界術(shù)語”的能量,所以也只能把它們一一列舉出來。對于初學者若造成理解上的偏差我表示道歉,總而言之你要記住:一個對象有兩類東西:一類記錄數(shù)據(jù),另一類記錄方法(方法總是做一件什么事,其中也包括返回新的數(shù)據(jù)),至于這兩類在不同的情境中叫法不一,也就要靠你自己去分辨了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/77968.html
摘要:在他的重學前端課程中提到到現(xiàn)在為止,前端工程師已經(jīng)成為研發(fā)體系中的重要崗位之一。大部分前端工程師的知識,其實都是來自于實踐和工作中零散的學習。一基礎(chǔ)前端工程師吃飯的家伙,深度廣度一樣都不能差。 開篇 前端開發(fā)是一個非常特殊的行業(yè),它的歷史實際上不是很長,但是知識之繁雜,技術(shù)迭代速度之快是其他技術(shù)所不能比擬的。 winter在他的《重學前端》課程中提到: 到現(xiàn)在為止,前端工程師已經(jīng)成為研...
摘要:在他的重學前端課程中提到到現(xiàn)在為止,前端工程師已經(jīng)成為研發(fā)體系中的重要崗位之一。大部分前端工程師的知識,其實都是來自于實踐和工作中零散的學習。一基礎(chǔ)前端工程師吃飯的家伙,深度廣度一樣都不能差。開篇 前端開發(fā)是一個非常特殊的行業(yè),它的歷史實際上不是很長,但是知識之繁雜,技術(shù)迭代速度之快是其他技術(shù)所不能比擬的。 winter在他的《重學前端》課程中提到: 到現(xiàn)在為止,前端工程師已經(jīng)成為研發(fā)體系...
摘要:作用域鏈的作用就是做標示符解析。事件循環(huán)還有個明顯的特點單線程。早期都是用作開發(fā),單線程可以比較好當規(guī)避同步問題,降低了開發(fā)門檻。單線程需要解決的是效率問題,里的解決思想是異步非阻塞。 0、前言 本人在大學時非常癡迷java,認為java就是世界上最好的語言,偶爾在項目中會用到一些javascript,但基本沒放在眼里。較全面的接觸javascript是在實習的時候,通過這次的了解發(fā)現(xiàn)...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。寫一個符合規(guī)范并可配合使用的寫一個符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個需求:在系統(tǒng)初始化時通過http獲取一個第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個接口,可通過...
摘要:是文檔的一種表示結(jié)構(gòu)。這些任務(wù)大部分都是基于它。這個實踐的重點是把你在前端練級攻略第部分中學到的一些東西和結(jié)合起來。一旦你進入框架部分,你將更好地理解并使用它們。到目前為止,你一直在使用進行操作。它是在前端系統(tǒng)像今天這樣復(fù)雜之前編寫的。 本文是 前端練級攻略 第二部分,第一部分請看下面: 前端練級攻略(第一部分) 在第二部分,我們將重點學習 JavaScript 作為一種獨立的語言,如...
摘要:一棧數(shù)據(jù)結(jié)構(gòu)與不同,中并沒有嚴格意義上區(qū)分棧內(nèi)存與堆內(nèi)存。引用數(shù)據(jù)類型的值是保存在堆內(nèi)存中的對象。不允許直接訪問堆內(nèi)存中的位置,因此我們不能直接操作對象的堆內(nèi)存空間。為了更好的搞懂變量對象與堆內(nèi)存,我們可以結(jié)合以下例子與圖解進行理解。 showImg(https://segmentfault.com/img/remote/1460000009784102?w=1240&h=683); ...
閱讀 2571·2021-11-22 09:34
閱讀 3548·2021-11-15 11:37
閱讀 2351·2021-09-13 10:37
閱讀 2111·2021-09-04 16:40
閱讀 1587·2021-09-02 15:40
閱讀 2466·2019-08-30 13:14
閱讀 3334·2019-08-29 13:42
閱讀 1910·2019-08-29 13:02