摘要:在向參數(shù)傳遞引用類型的值時(shí),會(huì)把這個(gè)值在內(nèi)存中的地址復(fù)制給一個(gè)局部變量,因此這個(gè)局部變量的變化會(huì)反映在函數(shù)的外部。當(dāng)在函數(shù)內(nèi)部重寫時(shí),這個(gè)變量的引用就是一個(gè)局部變量了,這個(gè)局部變量在函數(shù)執(zhí)行完畢后立即銷毀。
前言:我入門學(xué)的 java這種強(qiáng)類型語(yǔ)言,剛開(kāi)始學(xué)js第一感覺(jué)是挺簡(jiǎn)單,后來(lái)發(fā)現(xiàn)還是too young。所以,本次就把作用域、匿名函數(shù)做一個(gè)完整總結(jié),黑喂狗~~~
-------------------分割線----------------------
1.函數(shù) 返回值/參數(shù)返回值:::::::::::::::::::::::::
js的函數(shù)在定義時(shí)不必指定返回值,而且任何函數(shù)都可以通過(guò)return隨時(shí)返回值。
函數(shù)在執(zhí)行完return之后停止并立即退出,因此return后面的代碼永遠(yuǎn)不會(huì)執(zhí)行。
function sum(num1,num2){ return num1 + num2; alert("Hello World"); //這段代碼永遠(yuǎn)不會(huì)執(zhí)行 }
參數(shù):::::::::::::::
js函數(shù)不介意傳遞進(jìn)來(lái)多少個(gè)參數(shù),也不在乎傳遞進(jìn)來(lái)的是什么參數(shù)類型。
參數(shù)在內(nèi)部是由一個(gè)數(shù)組來(lái)表示的,函數(shù)接收的永遠(yuǎn)都是這個(gè)數(shù)組,函數(shù)體內(nèi)部可以通過(guò)arguments對(duì)象來(lái)訪問(wèn)這個(gè)參數(shù)數(shù)組,從而可以獲取傳遞給函數(shù)的每一個(gè)參數(shù)。
如下代碼:
function howManyArgs(){ alert(arguments.length); } howManyArgs("String",45); //2 howManyArgs(); //0 howManyArgs(12); //1
從上面的代碼可以看出來(lái),定義函數(shù)時(shí)沒(méi)有給函數(shù)指定參數(shù)名字,而調(diào)用時(shí)依然可以傳遞進(jìn)去任何數(shù)量和類型的參數(shù),因此在js函數(shù)中:命名的參數(shù)只是提供便利,但不是必須的。理解這點(diǎn)很重要。
不完美的重載:::::::::::::::::
既然可以用arguments.length判斷傳入?yún)?shù)的個(gè)數(shù),那么js函數(shù)也可以實(shí)現(xiàn)不完美的重載。
如下代碼:
function doAdd(){ if(arguments.length == 1){ alert(arguments[0] + 10); } if(arguments.length == 2){ alert(arguments[0] + arguments[1]); } } doAdd(10); //20 doAdd(30,20); //50
arguments[i]和對(duì)應(yīng)命名參數(shù)的關(guān)系:::::::::::::::::
看如下代碼:
function doAdd(num1,num2){ arguments[1] = 10; //重寫第二個(gè)參數(shù) alert(arguments[0] + num2); }
arguments對(duì)象中的值會(huì)自動(dòng)反映到對(duì)應(yīng)的命名參數(shù),但是讀取這兩個(gè)值不會(huì)訪問(wèn)相同的內(nèi)存空間,
修改命名參數(shù)并不會(huì)改變arguments中對(duì)應(yīng)的值
arguments對(duì)象長(zhǎng)度是由調(diào)用函數(shù)時(shí)傳入的參數(shù)個(gè)數(shù)決定的,不是由定義函數(shù)時(shí)的命名參數(shù)的個(gè)數(shù)決定的。
js中所有的函數(shù)都是按值傳遞的。
在向參數(shù)傳遞基本類型時(shí),被傳遞的值會(huì)被復(fù)制給一個(gè)局部變量。
在向參數(shù)傳遞引用類型的值時(shí),會(huì)把這個(gè)值在內(nèi)存中的地址復(fù)制給一個(gè)局部變量,因此這個(gè)局部變量的變化會(huì)反映在函數(shù)的外部。
來(lái)看幾個(gè)例子:
function addTen(num){ num += 10; return num; } var count = 20; var result = addTen(count); alert(count); //20,沒(méi)有變化 alert(result); //30
count傳遞給參數(shù)num,函數(shù)內(nèi)部num做了修改,但是沒(méi)有反映到count上。
function setName(obj){ obj.name = "Jack"; } var person = new Object(); setName(person); alert(person.name); //Jack
這個(gè)例子很容易讓人覺(jué)得,引用類型做為函數(shù)參數(shù)傳遞是按引用傳遞的,因?yàn)榫植康男薷模簅bj.name = "Jack",反映在了全局的作用域上:person.name,事實(shí)上并不是如此。
事實(shí)上:我們創(chuàng)建了一個(gè)對(duì)象,并把它保存在person變量中,然后把person當(dāng)做參數(shù)傳遞到setName()函數(shù)中復(fù)制給了obj,在這個(gè)函數(shù)內(nèi)部obj和person引用的是同一個(gè)對(duì)象。
再看一個(gè)例子:
function setName(obj){ obj.name = "Jack"; obj = new Object(); obj.name = "Rose"; } var person = new Object(); setName(person); alert(person.name); //Jack
這個(gè)例子中在setName()函數(shù)中,為obj重新定義了一個(gè)對(duì)象,另一行代碼為該對(duì)象定義了一個(gè)帶有不同值的name屬性。如果person傳遞給函數(shù)setName()之后是按引用傳遞的,那么對(duì)obj.name的修改就會(huì)反映到person.name上,事實(shí)上person.name依然是Jack。
當(dāng)在函數(shù)內(nèi)部重寫obj時(shí),這個(gè)變量的引用就是一個(gè)局部變量了,這個(gè)局部變量在函數(shù)執(zhí)行完畢后立即銷毀。
定義什么的太多了就不寫了,直接上代碼
var color = "blue"; function changeColor(){ var anotherColor = "red"; function swapColors(){ var tempColor = anotherColor; anotherColor = color; color = tempColor; //這里可以訪問(wèn) color,anotherColor 和tempColor } swapColor(); //這里可以訪問(wèn)color, anotherColor } changeColor(); //這里只能訪問(wèn)color
上面代碼中有三個(gè)執(zhí)行環(huán)境:全局環(huán)境、changeColor()的局部、和swapColors()的局部環(huán)境。
全局環(huán)境中有一個(gè)color變量和changeColor()函數(shù)。
changeColor()的局部環(huán)境中有一個(gè)名為anotherColor的變量和一個(gè)swapColors()的函數(shù),但是它也可以訪問(wèn)全局環(huán)境中的變量color
swapColors()局部環(huán)境中有一個(gè)變量tempColor,只能在這個(gè)環(huán)境中訪問(wèn)到。
無(wú)論是全局環(huán)境還是changeColor()的局部環(huán)境都無(wú)權(quán)訪問(wèn)tempColor,在swapColors()內(nèi)部可以訪問(wèn)其他兩個(gè)環(huán)境中的所有變量,因?yàn)槟莾蓚€(gè)環(huán)境是它的父執(zhí)行環(huán)境。
總結(jié):內(nèi)部環(huán)境可以通過(guò)作用域鏈訪問(wèn)所有的外部環(huán)境,但外部環(huán)境不能訪問(wèn)內(nèi)部環(huán)境中的任何變量和函數(shù),每個(gè)環(huán)境內(nèi)部沒(méi)有這個(gè)變量或者函數(shù)時(shí),都可以向上搜索變量和函數(shù)名,直到找到為止。
沒(méi)有塊級(jí)作用域java等語(yǔ)言話括號(hào)括起來(lái)的代碼塊都有自己的作用域,但是js中總有例外,看下面代碼:
if(true){ var color = "blue"; } alert(color); //blue
這里是在if語(yǔ)句中定義了一個(gè)變量color,和作用域函數(shù)里面定義變量的例子不同,在if語(yǔ)句中的變量聲明將添加到當(dāng)前的執(zhí)行環(huán)境中,看下面for循環(huán)的例子:
for(var i = 0; i<10; i++){ doSomething(i); } alert(i); //10
對(duì)于js,由for語(yǔ)句創(chuàng)建的變量i即使在for循環(huán)執(zhí)行結(jié)束后,也依舊會(huì)存在于循環(huán)外部的執(zhí)行環(huán)境。
4.匿名函數(shù)看下面例子:
window.onload = function(){ alert("Hello World"); }; var person = { callName: function(){ alert("My name is Jack"); } }; person.callName(); setTimeout( function(){alert("Hello World");}, 500);
1.首先,為load事件創(chuàng)建了一個(gè)函數(shù)做為事件處理程序,不會(huì)直接調(diào)用這個(gè)函數(shù),而是在頁(yè)面加載時(shí)自動(dòng)調(diào)用,所以沒(méi)必要為這個(gè)函數(shù)命名,像這樣:
function sayHello(){alert("Hello World");}; window.onload = sayHello;
2.聲明了一個(gè)匿名函數(shù),做為person對(duì)象的一個(gè)屬性callName,可以通過(guò)該屬性來(lái)調(diào)用這個(gè)方法:
如:person.callName();
3.將匿名函數(shù)做為回調(diào)函數(shù)傳遞給另外一個(gè)函數(shù),代碼中將匿名函數(shù)做為一個(gè)參數(shù)傳遞給window對(duì)象的setTimeout()方法,該方法將在半秒后被調(diào)用。
-------------------------------------------------------end--------------------------------------------------------
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79711.html
摘要:前言最近在學(xué)前幾天看到兩道題剛開(kāi)始看懵懵懂懂這幾天通過(guò)各種查資料慢慢的理解頓悟了對(duì)匿名函數(shù)閉包立即執(zhí)行函數(shù)的理解也更深了一點(diǎn)在此分享給大家我的理解與總結(jié)希望能幫助大家理解因?yàn)檫@篇文章是我用心總結(jié)的查閱了很多的資料所以總結(jié)的比較細(xì)篇幅較長(zhǎng)如果 前言 最近在學(xué)JS,前幾天看到兩道題,剛開(kāi)始看懵懵懂懂,這幾天通過(guò)各種查資料,慢慢的理解,頓悟了,對(duì)匿名函數(shù),閉包,立即執(zhí)行函數(shù)的理解也更深了一點(diǎn)...
摘要:執(zhí)行返回的內(nèi)部函數(shù),依然能訪問(wèn)變量輸出閉包中的作用域鏈理解作用域鏈對(duì)理解閉包也很有幫助。早期的版本里采用是計(jì)數(shù)的垃圾回收機(jī)制,閉包導(dǎo)致內(nèi)存泄露的一個(gè)原因就是這個(gè)算法的一個(gè)缺陷。 關(guān)于閉包,我翻了幾遍書,看了幾遍視頻,查了一些資料,可是還是迷迷糊糊的,干脆自己動(dòng)手來(lái)個(gè)總結(jié)吧 !歡迎指正... (~ o ~)~zZ 1. 什么是閉包? 來(lái)看一些關(guān)于閉包的定義: 閉包是指有權(quán)...
摘要:閉包引起的內(nèi)存泄漏總結(jié)從理論的角度將由于作用域鏈的特性中所有函數(shù)都是閉包但是從應(yīng)用的角度來(lái)說(shuō)只有當(dāng)函數(shù)以返回值返回或者當(dāng)函數(shù)以參數(shù)形式使用或者當(dāng)函數(shù)中自由變量在函數(shù)外被引用時(shí)才能成為明確意義上的閉包。 文章同步到github js的閉包概念幾乎是任何面試官都會(huì)問(wèn)的問(wèn)題,最近把閉包這塊的概念梳理了一下,記錄成以下文章。 什么是閉包 我先列出一些官方及經(jīng)典書籍等書中給出的概念,這些概念雖然...
摘要:閉包的學(xué)術(shù)定義先來(lái)參考下各大權(quán)威對(duì)閉包的學(xué)術(shù)定義百科閉包,又稱詞法閉包或函數(shù)閉包,是引用了自由變量的函數(shù)。所以,有另一種說(shuō)法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。 前言 上一章講解了閉包的底層實(shí)現(xiàn)細(xì)節(jié),我想大家對(duì)閉包的概念應(yīng)該也有了個(gè)大概印象,但是真要用簡(jiǎn)短的幾句話來(lái)說(shuō)清楚,這還真不是件容易的事。這里我們就來(lái)總結(jié)提煉下閉包的概念,以應(yīng)付那些非專人士的心血來(lái)潮。 閉包的學(xué)術(shù)...
摘要:一般來(lái)講,函數(shù)執(zhí)行完畢后,局部活動(dòng)對(duì)象就會(huì)被銷毀,內(nèi)存中僅保存全局作用域,但是閉包的情況有所不同理解閉包的前提先理解另外兩個(gè)內(nèi)容作用域鏈垃圾回收作用域鏈當(dāng)代碼在執(zhí)行過(guò)程中,會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈。 閉包是javascript語(yǔ)言的一個(gè)難點(diǎn),也是它的特色,很多高級(jí)應(yīng)用都要依靠閉包來(lái)實(shí)現(xiàn)。個(gè)人的理解是:函數(shù)中嵌套函數(shù)。 閉包的定義及其優(yōu)缺點(diǎn) 閉包是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的...
閱讀 2534·2021-10-19 11:45
閱讀 2529·2021-09-30 09:56
閱讀 1507·2021-09-30 09:47
閱讀 636·2019-08-30 15:53
閱讀 1878·2019-08-30 15:44
閱讀 615·2019-08-30 12:52
閱讀 1125·2019-08-30 11:16
閱讀 1660·2019-08-29 16:36