解析JavaScript面向?qū)ο蟾拍钪械腛bject類型與作用域
引用類型
引用類型主要包括:Object 類型、Array 類型、Date 類型、RegExp 類型、Function 類型等等。
引用類型使用時(shí),需要從它們身上生成一個(gè)對(duì)象(實(shí)例)。也就是說(shuō),引用類型相當(dāng)于一個(gè)模版,當(dāng)我們想要用某個(gè)引用類型的時(shí)候,就需要用這個(gè)模版來(lái)生成一個(gè)對(duì)象來(lái)使用,所以引用類型有時(shí)候也稱作對(duì)象定義。
例如,我們需要生成一個(gè) person 對(duì)象,來(lái)定義某人的個(gè)人信息和行為,那么我們就需要依賴 Object 類型:
var person = new Object(); person.name = "jiangshui"; person.sayName = function(){ console.log(this.name); }
上面的這個(gè) person 對(duì)象,通過(guò) new 操作符使用 Object 類型這個(gè)“模版”定義。之后就可以對(duì)這個(gè)對(duì)象添加屬性 name 和方法 sayName 了。屬性和方法是 Object 類型具有的“功能”,所以通過(guò) Object 等引用類型創(chuàng)建的對(duì)象就可以用這個(gè)了。
創(chuàng)建對(duì)象不一定非得需要用 new 操作符,有一些類型可以簡(jiǎn)化的創(chuàng)建,例如創(chuàng)建一個(gè)上面那樣的 Object 類型的對(duì)象,也可以使用下面兩種方法:
var person = {}; person.name = "jiangshui"; person.sayName = function(){ console.log(this.name); }
或
var person = { name : "jiangshui", sayName : function(){ console.log(this.name); } };
{}操作符的功能就跟 new Object() 一樣,簡(jiǎn)化了操作。上面兩種寫(xiě)法也有一些區(qū)別,第一種是“追加”,也就是在之前的定義中,繼續(xù)添加屬性或者方法,如果之前已經(jīng)存在了同名屬性方法,則會(huì)覆蓋。而第二種是“取代”,就是不管前面是否定義 person 對(duì)象的屬性和方法,這個(gè)方法會(huì)用新定義的內(nèi)容,整個(gè)替換掉之前定義的。因?yàn)橐妙愋蜕傻膶?duì)象,是儲(chǔ)存在內(nèi)存中的一塊區(qū)域,然后將其指針保存在某變量中(person),第二種寫(xiě)法,是生成了一個(gè)新對(duì)象(新內(nèi)存區(qū)域),然后將 person 變量指向了新內(nèi)存區(qū)域,所以就把之前的取代了。了解這一點(diǎn)對(duì)后面理解,至關(guān)重要。
其他引用類型的用法大致一致,例如 Array 類型,也可以用 [] 來(lái)生成對(duì)象,或者直接定義。生成數(shù)組對(duì)象之后,就可以按照數(shù)組的格式存儲(chǔ)信息內(nèi)容,此外對(duì)象會(huì)得到 Array 類型中定義的那些方法,例如 push、shift、sort 等等,就可以調(diào)用這些方法,例如:
var colors = []; colors.push('red','green'); console.log(colors);
上面代碼就是通過(guò) Array 類型創(chuàng)建一個(gè)數(shù)組類型的對(duì)象,然后調(diào)用 Array 類型里面之前定義的 push 方法,向?qū)ο罄锩嫣砑恿?red 和 green 兩個(gè)值,最后在控制臺(tái)打印出來(lái),就可以看到了。
call 和 apply 方法
這兩個(gè)方法是 Function 類型提供的,也就是說(shuō),可以在函數(shù)上面使用。call 和 apply 方法的功能一樣,就是可以擴(kuò)充函數(shù)運(yùn)行的作用域,區(qū)別就在于使用 call 的時(shí)候,傳遞給函數(shù)的參數(shù)必須逐個(gè)列舉出來(lái),而 apply 方法卻不用。這樣可以根據(jù)自己函數(shù)的要求來(lái)決定使用 call 或者 apply。
擴(kuò)充函數(shù)運(yùn)行的作用域是什么意思?舉個(gè)例子你就明白了。
你可以這樣理解,函數(shù)被包裹在一個(gè)容器(作用域)里面,在這個(gè)容器里面存在一些變量或者其他東西,當(dāng)函數(shù)運(yùn)行,調(diào)用這些變量等,就會(huì)在當(dāng)前容器里面找這個(gè)東西。這個(gè)容器其實(shí)外面還包裹了一個(gè)更大的容器,如果當(dāng)前小容器沒(méi)有的話,函數(shù)會(huì)到更大的容器里面尋找,依次類推,一直找到最大的容器 window 對(duì)象。但是如果函數(shù)在當(dāng)前小容器里面運(yùn)行的時(shí)候,小容器里面有對(duì)應(yīng)變量等,即便是大容器里面也有,函數(shù)還是會(huì)調(diào)用自己容器里面的。
而 call 和 apply 方法,就是解決這個(gè)問(wèn)題,突破容器的限制。就前面例子:
var person = { name : "jiangshui", sayName : function(){ console.log(this.name); } };
打開(kāi) Chrome 的 Console 之后,粘貼進(jìn)去執(zhí)行一下,之后再執(zhí)行 person.sayName() 可以看到
這時(shí)候,person 就是一個(gè)容器,其中創(chuàng)建了一個(gè) sayName 方法(函數(shù)),執(zhí)行的時(shí)候,必須在 person 作用域下面執(zhí)行。當(dāng)在最下面直接執(zhí)行的時(shí)候,也就是在 window 的作用域下面執(zhí)行會(huì)報(bào)錯(cuò) not defined,因?yàn)?window 下面沒(méi)有定義 sayName 方法。而里面的 this 指針,是一個(gè)比較特殊的東西,它指向當(dāng)前作用域,this.name 的意思,就是調(diào)用當(dāng)前作用域下面的 name 值。
下面我們?yōu)?window 對(duì)象添加一個(gè) name 屬性:
window.name = "yujiangshui";
或者直接
name = "yujiangshui";
因?yàn)?window 是最大的容器,所以 window 可以省略掉,所有定義的屬性或者變量,都掛靠到 window 上面去了,不信可以看:
那現(xiàn)在我們就想在 window 這個(gè)大容器下面,運(yùn)行 person 小容器里面的 sayName 方法,就需要用 call 或 apply 來(lái)擴(kuò)充 sayName 方法的作用域。執(zhí)行下面語(yǔ)句:
person.sayName.call(window);
或者
person.sayName.call(this);
輸出的結(jié)果都是一樣的,你也可以換用 apply 看看效果,因?yàn)檫@個(gè) demo 太簡(jiǎn)單的,不需要傳遞參數(shù),所以 call 和 apply 功能效果就完全一致了。
解釋一下上面代碼,sayName 首先是 Function 類型的實(shí)例,也就具有了 call 方法和 apply 方法,call 和 apply 方法既然是 Function 類型的方法,所以就需要用這種方式調(diào)用 person.sayName.call(window) 而不是什么 person.sayName().call(window) 之類的。
然后 call 和 apply 方法的參數(shù),就是一個(gè)作用域(對(duì)象),表示將前面的函數(shù)在傳遞進(jìn)去的作用域下面運(yùn)行。將 window 這對(duì)象傳遞進(jìn)去之后,sayName 方法中的 this.name 指向的就是 window.name,于是就擴(kuò)充了作用域。
為什么傳遞 window 和 this 都是一樣的效果?因?yàn)槲覀儺?dāng)前執(zhí)行這個(gè)函數(shù)的位置是 window,前面說(shuō)過(guò) this 指針指向的是當(dāng)前作用域,所以 this 指向的就是 window,所以就等于 window。
- JavaScript面向?qū)ο缶帉?xiě)購(gòu)物車功能
- JS 面向?qū)ο笾^承---多種組合繼承詳解
- javascript面向?qū)ο蟪绦蛟O(shè)計(jì)高級(jí)特性經(jīng)典教程(值得收藏)
- JS實(shí)現(xiàn)簡(jiǎn)單面向?qū)ο蟮念伾x擇器實(shí)例
- JS面向?qū)ο缶幊淘斀?/a>
- JS面向?qū)ο螅?)之Object類,靜態(tài)屬性,閉包,私有屬性, call和apply的使用,繼承的三種實(shí)現(xiàn)方法
- 學(xué)習(xí)Javascript面向?qū)ο缶幊讨庋b
- js面向?qū)ο蟮膶?xiě)法
- 深入淺析JavaScript面向?qū)ο蠛驮秃瘮?shù)
- Javascript之面向?qū)ο?-方法
相關(guān)文章
javascript實(shí)現(xiàn)playfair和hill密碼算法
這篇文章主要介紹了javascript實(shí)現(xiàn)playfair和hill密碼算法,需要的朋友可以參考下2014-12-12javascript下判斷一個(gè)對(duì)象是否具有指定名稱的屬性的的代碼
hasOwnProperty 方法 返回一個(gè)布爾值,指出一個(gè)對(duì)象是否具有指定名稱的屬性。2010-01-01通過(guò)一段代碼簡(jiǎn)單說(shuō)js中的this的使用
本文通過(guò)一段代碼與大家簡(jiǎn)單說(shuō)說(shuō)js中this的使用及相關(guān)問(wèn)題,感興趣的朋友可以參考下哈,希望對(duì)大家有所幫助2013-07-07使用JavaScript 實(shí)現(xiàn)各種跨域的方法
本篇文章是對(duì)在JavaScript中實(shí)現(xiàn)各種跨域方法的介紹。需要的朋友參考下2013-05-05JS 模態(tài)對(duì)話框和非模態(tài)對(duì)話框操作技巧匯總
模態(tài)窗口javascript 技巧包括傳值、打開(kāi)、刷新以及相關(guān)實(shí)例學(xué)習(xí),感興趣的朋友可以參考下哈2013-04-04JavaScript window.location對(duì)象
這篇文章主要介紹了JavaScript window.location對(duì)象的相關(guān)資料,需要的朋友可以參考下2014-11-11javascript學(xué)習(xí)筆記(三)BOM和DOM詳解
本文應(yīng)用了很多實(shí)例,來(lái)解讀JavaScript中BOM和DOM,DOM是一個(gè)使程序和腳本有能力動(dòng)態(tài)地訪問(wèn)和更新文檔的內(nèi)容、結(jié)構(gòu)以及樣式的平臺(tái)和語(yǔ)言中立的接口。,而B(niǎo)OM定義了JavaScript可以進(jìn)行操作的瀏覽器的各個(gè)功能部件的接口。2014-09-09