JavaScript修改作用域外變量的方法
1.今天在看JavaScript學(xué)習(xí)指南的時候做的課后習(xí)題,也因此詳細(xì)的對函數(shù)的傳入?yún)?shù)進(jìn)行比較深入的研究.
題目如下:
函數(shù)如何才能修改其作用域之外的變量?編寫一個函數(shù),由1~5的數(shù)字組成的數(shù)組作為參數(shù),調(diào)用該函數(shù)后將把其中的數(shù)字項替換為相應(yīng)的字符串表示形式.
需要注意知識點(diǎn):
在JavaScript中函數(shù)參數(shù)的傳遞,對于基于原始值的參數(shù)進(jìn)行值傳遞(數(shù)字,字符串,布爾值),函數(shù)中的修改不會影響實(shí)際參數(shù)值.而傳遞給函數(shù)的參數(shù)而言,對象是一個引用,對其的修改的將會反映在主調(diào)程序中.<-但是,會有這樣的情況,如下
var outer_number = ; var outer_boolean = true; var outer_array = [,,]; var outer_object = {test:""}; function display(num,bool,arr,obj){ console.log("number:"+num+"\nboolean:"+bool+"\narray:"+arr+"\nobject:"+obj.test); } function test(num,bool,arr,obj){ display(num,bool,arr,obj);//num=,bool=true,array=[,,],object.test= num = ; bool = false; arr[] = ; obj.test = ""; display(num,bool,arr,obj);//num=,bool=false,array=[,,,],object.test= arr = [,,]; obj = {test:""}; display(num,bool,arr,obj);//num=,bool=false,array=[,,],object.test= } test(outer_number,outer_boolean,outer_array,outer_object); display(outer_number,outer_boolean,outer_array,outer_object);//num = ,bool=true,array=[,,,],object.test=
在上面代碼中我們創(chuàng)建了4個全局變量,類型分別為數(shù)字,布爾值,數(shù)組,對象.2個函數(shù),display和test.
display執(zhí)行了4次,分別結(jié)果如下:
"number:2
boolean:true
array:1,2,3
object:122"<-傳入函數(shù)時的值
"number:0
boolean:false
array:1,2,3,3
object:134"<-執(zhí)行更改
"number:0
boolean:false
array:3,2,1
object:133"<-重新賦值
"number:2
boolean:true
array:1,2,3,3
object:134"<-函數(shù)執(zhí)行完畢后
可以看出我們對數(shù)組和對象的重新賦值并沒有成功,如果按引用傳遞,那么我們應(yīng)該也對全局變量的數(shù)組和對象重新賦值修改了呀.
其實(shí)JavaScript中所謂的按引用賦值并不是真正意義上的按引用復(fù)制,準(zhǔn)確說應(yīng)該是按共享傳遞.也可以叫按對象傳遞,按對象共享傳遞(call by sharing).
在這個按共享傳遞的條件下,我們獲取的引用可以說只是實(shí)參引用的副本,它和我們經(jīng)常說的按引用傳遞的最大差別就在于我們在對引用副本的賦值不會影響實(shí)參的值,正如我們上面那樣做的那樣,賦值操作是不可行的.
當(dāng)然我們從對象類型和基本類型兩方面看,對象是可變的而基本類型是不可變的(注意!字符串修改其實(shí)是返回的新的字符串),所以按共享傳遞對于基本類型來說也是符合按共享傳遞的.
總結(jié)一下:
JavaScript中,基本類型和對象都按共享傳遞(call by sharing),但是由于JavaScript的基本類型的不變性,基本類型按共享傳遞與按值傳遞沒有任何區(qū)別,而對象按共享傳遞.
按共享傳遞(call by sharing):傳遞的是實(shí)參引用的副本,我們對引用副本的賦值不影響實(shí)參的值,但是可以使用引用副本去修改引用的內(nèi)容.詳細(xì)的wiki地址
函數(shù)對傳入的參數(shù):
1.基本類型,按值傳遞(或者也可以說按共享傳遞),內(nèi)部賦值修改都不影響主調(diào)程序
2.對象類型,按共享傳遞,傳入的為實(shí)參引用的副本,內(nèi)部對該引用的賦值無效,對對象屬性的賦值修改有效.
大概就是這么理解了,假如有什么地方我犯了什么錯誤,也希望能被指出來.
下面單獨(dú)拉出JavaScript作用域
任何程序設(shè)計語言都有作用域的概念,簡單的說,作用域就是變量與函數(shù)的可訪問范圍,即作用域控制著變量與函數(shù)的可見性和生命周期。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種。
全局作用域(Global Scope)
在代碼中任何地方都能訪問到的對象擁有全局作用域,一般來說以下幾種情形擁有全局作用域:
?。?)最外層函數(shù)和在最外層函數(shù)外面定義的變量擁有全局作用域,例如:
var authorName="山邊小溪"; function doSomething(){ var blogName="夢想天空"; function innerSay(){ alert(blogName); } innerSay(); } alert(authorName); //山邊小溪 alert(blogName); //腳本錯誤 doSomething(); //夢想天空 innerSay() //腳本錯誤
(2)所有末定義直接賦值的變量自動聲明為擁有全局作用域,例如:
function doSomething(){ var authorName="山邊小溪"; blogName="夢想天空"; alert(authorName); } doSomething(); //山邊小溪 alert(blogName); //夢想天空 alert(authorName); //腳本錯誤
變量blogName擁有全局作用域,而authorName在函數(shù)外部無法訪問到。
?。?)所有window對象的屬性擁有全局作用域
一般情況下,window對象的內(nèi)置屬性都擁有全局作用域,例如window.name、window.location、window.top等等。
1. 局部作用域(Local Scope)
和全局作用域相反,局部作用域一般只在固定的代碼片段內(nèi)可訪問到,最常見的例如函數(shù)內(nèi)部,所有在一些地方也會看到有人把這種作用域稱為函數(shù)作用域,例如下列代碼中的blogName和函數(shù)innerSay都只擁有局部作用域。
function doSomething(){ var blogName="夢想天空"; function innerSay(){ alert(blogName); } innerSay(); } alert(blogName); //腳本錯誤 innerSay(); //腳本錯誤
相關(guān)文章
一文詳解JS中的Map、Set、WeakMap和WeakSet
在JavaScript中,Map、Set、WeakMap和WeakSet是四個不同的數(shù)據(jù)結(jié)構(gòu),它們都有不同的特點(diǎn)和用途,本文詳細(xì)介紹了Map、Set、WeakMap和WeakSet的用法及區(qū)別,需要的朋友可以參考下2023-04-04淺析document.createDocumentFragment()與js效率
對于循環(huán)批量操作頁面的DOM有很大幫助!利用文檔碎片處理,然后一次性append,并且使用原生的javascript語句操作2013-07-07至2023年最好用的兼容多瀏覽器的原生js復(fù)制函數(shù)copyText
因為后臺需要增加一些復(fù)制一些內(nèi)容非表單中內(nèi)容,那么下面這個函數(shù)就非常的好用了,其實(shí)也是利用了表單的數(shù)據(jù)權(quán)限比較容易突破,下面是具體的實(shí)現(xiàn)函數(shù),大家可以拿走2023-05-05JavaScript新功能介紹之findLast()和findLastIndex()
最近工作中遇到了一個關(guān)于查找數(shù)組里面的目標(biāo)元素的方法,所以下面這篇文章主要給大家介紹了關(guān)于JavaScript新功能之findLast()?和findLastIndex()的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04el-table動態(tài)渲染列、可編輯單元格、虛擬無縫滾動的實(shí)現(xiàn)
vue對數(shù)據(jù)處理很常見,本文主要介紹了對el-table組件二次封裝,包括對el-table的動態(tài)渲染、單元格編輯;對于無縫滾動的實(shí)現(xiàn),優(yōu)化大數(shù)據(jù)量下的頁面卡頓問題,感興趣的可以了解一下2023-12-12BootStrap學(xué)習(xí)系列之布局組件(下拉,按鈕組[toolbar],上拉)
這篇文章主要介紹了BootStrap學(xué)習(xí)系列之布局組件(下拉,按鈕組[toolbar],上拉)的相關(guān)資料,需要的朋友可以參考下2017-01-01Openlayers實(shí)現(xiàn)擴(kuò)散的動態(tài)點(diǎn)(水紋效果)
這篇文章主要為大家詳細(xì)介紹了Openlayers實(shí)現(xiàn)擴(kuò)散的動態(tài)點(diǎn),水紋效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-08-08JS實(shí)現(xiàn)選項卡插件的兩種寫法(jQuery和class)
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)選項卡插件的兩種寫法:jQuery和class,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-12-12