javascript管中窺豹 形參與實(shí)參淺析
更新時(shí)間:2011年12月17日 23:47:18 作者:
本想從語(yǔ)言的角度來(lái)分析,無(wú)奈功力不夠,只能粗淺的嘗試一下,于是稱之管中窺豹,還望大牛指正
引子:
今天看到別人的一個(gè)題目:
function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
}
fn()
感覺(jué)自己對(duì)這也是一知半解,自己也可以試一下,于是就特地分析一下。
本想從語(yǔ)言的角度來(lái)分析,無(wú)奈功力不夠,只能粗淺的嘗試一下,于是稱之管中窺豹,還望大牛指正。
這是昨天寫(xiě)的,今天吃飯的時(shí)候又想了一下,想來(lái)想去感覺(jué)有些問(wèn)題還是說(shuō)得不靠譜,于是又試著修改了一下。
每一本js入門(mén)書(shū)籍都會(huì)提到,JS的函數(shù)內(nèi)部有一個(gè)Arguments的對(duì)象arguments,用來(lái)函數(shù)調(diào)用的時(shí)候?qū)嶋H傳入函數(shù)的參數(shù),fn.length保存形參的長(zhǎng)度。
這些對(duì)分析來(lái)說(shuō)略有用處,可是我想得到更多形參的信息,不知道有誰(shuí)有比較好的辦法,我暫時(shí)無(wú)解。
于是只能模擬了。
先不理會(huì)模擬,從實(shí)際問(wèn)題出發(fā):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<script type="text/javascript">
//形參中含有隱形的聲明var x = undefined
function fn(x){
console.log(x,arguments[0]);
arguments[0] = 2;
console.log(x,arguments[0]);
}
console.log('fn():');
fn();
//undefined , undefined
//undefined , 2
console.log('fn(1):');
fn(1);
//1,1
//2,2
重點(diǎn)關(guān)注后面兩個(gè)函數(shù)(fn_1,fn_2)的執(zhí)行,在這里,我們直接重新聲明了形參對(duì)應(yīng)的x,看到網(wǎng)上有的人說(shuō)這是聲明的一個(gè)局部變量x。
也是,不過(guò)這個(gè)局部變量不是一般的局部變量,x直接關(guān)聯(lián)對(duì)應(yīng)的arguments,上面的實(shí)例中就是x關(guān)聯(lián)arguments[0];
所以我猜測(cè)這個(gè)賦值的流程應(yīng)該是
1、函數(shù)定義的時(shí)候,聲明了形參,如果函數(shù)體內(nèi)有相同名稱的局部變量,則忽略此聲明。同時(shí)函數(shù)體內(nèi)同時(shí)會(huì)有一個(gè)對(duì)象arguments;
(亂入一句:個(gè)人以為arguments當(dāng)初不定義成數(shù)組的一個(gè)考慮是否是因?yàn)樵诤瘮?shù)定義內(nèi)無(wú)法確定實(shí)際參數(shù)的個(gè)數(shù)[運(yùn)行時(shí)動(dòng)態(tài)確定],那么要么這個(gè)數(shù)組無(wú)限大,要么數(shù)組一取值就越界)。
回到正題:
對(duì)于fn_2,初始化形參相當(dāng)于var x;(此時(shí)x沒(méi)有賦值,默認(rèn)為undefined,賦值是在語(yǔ)句執(zhí)行的時(shí)候賦值的)
所以如果可以這么寫(xiě)的話,fn_2就應(yīng)該是這樣:
function fn_2(var x){
x = 3;
console.log(x,arguments[0]);
arguments[0] = 2;
console.log(x,arguments[0]);
}
2、函數(shù)語(yǔ)法檢測(cè)通過(guò),執(zhí)行的時(shí)候,函數(shù)內(nèi)部的arguments對(duì)象一開(kāi)始就得到賦值,賦值完畢后,函數(shù)體內(nèi)的語(yǔ)句開(kāi)始執(zhí)行。
下面的一段表述是我自己想的,不知道正確不正確(特別是關(guān)聯(lián)的說(shuō)法):
一旦發(fā)現(xiàn)形參(對(duì)應(yīng)的變量)被賦值,那么會(huì)去尋找arguments對(duì)應(yīng)的項(xiàng),如果發(fā)現(xiàn)了arguments對(duì)應(yīng)的項(xiàng),那么設(shè)置形參與arguments對(duì)應(yīng)項(xiàng)的關(guān)聯(lián)。如果沒(méi)有發(fā)現(xiàn)arguments里面對(duì)應(yīng)的項(xiàng)(undefined),那么形參和arguments還是保持獨(dú)立。這里尋找的是arguments在函數(shù)運(yùn)行開(kāi)始的一個(gè)快照。反過(guò)來(lái)arguments賦值也是一樣。
上面的刪除的部分是昨天的,紅字部分是寫(xiě)到一半的時(shí)候發(fā)現(xiàn)有問(wèn)題加上去的。今天回過(guò)神來(lái),昨天為什么要傻逼的想到快照呢,這個(gè)不就是函數(shù)開(kāi)始運(yùn)行時(shí)直接
判斷關(guān)聯(lián)么?于是改了一下表述:
在函數(shù)開(kāi)始執(zhí)行時(shí),設(shè)置形參與arguments的關(guān)聯(lián)信息。如果形參與對(duì)應(yīng)的arguments里面能找到對(duì)應(yīng)的項(xiàng)(均為undefined),那么兩者關(guān)聯(lián)。后面不論怎么處理,都不會(huì)改變整個(gè)函數(shù)體內(nèi)的關(guān)聯(lián)信息。
于是后面的實(shí)例說(shuō)明的說(shuō)法也要改變:
回到例子,fn_2函數(shù)語(yǔ)法檢測(cè)通過(guò),從第二步開(kāi)始執(zhí)行:
不帶參數(shù)的情況
fn_2();
function fn_2(x){//arguments賦值完成,由于沒(méi)有實(shí)參,于是arguments參數(shù)列表為空。同時(shí)判斷關(guān)聯(lián)信息,顯然形參有,arguments空,兩者相互獨(dú)立,以后都不會(huì)再關(guān)聯(lián)
var x = 3;//x賦值為3,x與arguments[0]相互獨(dú)立,arguments[0]還是為undefined
console.log(x,arguments[0]);//打印x=3,arguments[0]為undefined
arguments[0] = 2;//arguments被賦值,x與arguments[0]相互獨(dú)立。因此x=3不改變
console.log(x,arguments[0]);//打印x = 3,arguments[0]=2
}
帶參數(shù)的情況
帶參數(shù)的情況 fn_2(1);
function fn_2(x){//arguments賦值完成,arguments[0]=1。同時(shí)形參x有值,兩者相關(guān)聯(lián),永結(jié)同心。
var x = 3;//x賦值為3,x與arguments[0]關(guān)聯(lián),于是arguments[0]被賦值為3,。
console.log(x,arguments[0]);//打印x=3,arguments[0] = 3
arguments[0] = 2;//arguments[0]被賦值2,由于x與arguments[0]已經(jīng)關(guān)聯(lián)到一起,于是x同時(shí)改變
console.log(x,arguments[0]);//打印x = 2,arguments[0]=2
}
反過(guò)來(lái)應(yīng)該也是一樣的:
不帶參數(shù)
fn_2();
function fn_2(x){//不關(guān)聯(lián)
arguments[0] = 2;//找不到對(duì)應(yīng)的x(undefined),相互獨(dú)立
console.log(x,arguments[0]);//undefined,2
x = 3;//相互獨(dú)立,快照。雖然arguments動(dòng)態(tài)添加了,老死不相往來(lái),所以依舊失敗
console.log(x,arguments[0]);//3,2
}
帶參數(shù)
fn_2(1);
function fn_2(x){
arguments[0] = 2;//關(guān)聯(lián)
console.log(x,arguments[0]);//2,2
x = 3;//關(guān)聯(lián)
console.log(x,arguments[0]);//3,3
}
由于我們只有一個(gè)形參,可能說(shuō)服力不夠,現(xiàn)在增加到兩個(gè)。
只有一個(gè)實(shí)參的情況:
fn_2(1);
function fn_2(x,y){ //arguments賦值完成,arguments[0]=1,arguments[1]=undefined,因此只有x與arguments[0]關(guān)聯(lián),y與arguments[1]老死不往來(lái)
console.log(x,y,arguments[0],arguments[1]); //1,undefined,1,undefined
var x = 3; //x賦值為3,x與arguments[0]關(guān)聯(lián),于是arguments[0]被賦值為3。
console.log(x,y,arguments[0],arguments[1]); //3,undefined,3,undefined
var y = 4; //y賦值為3,y與arguments[1]相互獨(dú)立,arguments[1]還是為undefined
console.log(x,y,arguments[0],arguments[1]); //3,4,3,undefined
arguments[0] = 2; //arguments[0]被賦值2,由于x與arguments[0]已經(jīng)關(guān)聯(lián)到一起,于是x同時(shí)改變
console.log(x,y,arguments[0],arguments[1]); //2,4,2,undefined
arguments[1] = 5; //arguments[1]被賦值5,y與arguments[1]相互獨(dú)立,于是y還是保持為4
console.log(x,y,arguments[0],arguments[1]); //x=2,y=4,arguments[0]=2,arguments[1]=5
}
有兩個(gè)實(shí)參的情況:
fn_3(1,6);
function fn_3(x,y){ //arguments賦值完成,arguments[0]=1,arguments[1]=6,x與arguments[0],y與arguments[1]都相互關(guān)聯(lián)
console.log(x,y,arguments[0],arguments[1]); //1,6,1,6
var x = 3; //x賦值為3,x與arguments[0]關(guān)聯(lián),于是arguments[0]被賦值為3。
console.log(x,y,arguments[0],arguments[1]); //3,6,3,6
var y = 4; //y賦值為3,y與arguments[1]關(guān)聯(lián),于是arguments[1]被賦值為4。
console.log(x,y,arguments[0],arguments[1]); //3,4,3,4
arguments[0] = 2; //arguments[0]被賦值2,由于x與arguments[0]已經(jīng)關(guān)聯(lián)到一起,于是x同時(shí)改變
console.log(x,y,arguments[0],arguments[1]); //2,4,2,4
arguments[1] = 5; //arguments[1]被賦值5,由于y與arguments[1]已經(jīng)關(guān)聯(lián)到一起,于是y同時(shí)改變
console.log(x,y,arguments[0],arguments[1]); //x=2,y=5,arguments[0]=2,arguments[1]=5
}
以上全部是推測(cè),因?yàn)閷?shí)際中沒(méi)有辦法形參的信息,所以我按照推測(cè)寫(xiě)了一個(gè)小測(cè)試:
下面的也改了:
function _Function(){//獲得的形參列表為數(shù)組:_args
var _args = [];
for(var i = 0; i < arguments.length - 1; i++){
var obj = {};
obj['key'] = arguments[i];
obj[arguments[i]] = undefined;
_args.push(obj);
}
//this._argu = _args;
var fn_body = arguments[arguments.length - 1];
//下面的方法獲取實(shí)參_arguments,這里_arguments實(shí)現(xiàn)為一個(gè)數(shù)組,而非arguments對(duì)象
this.exec = function(){
//函數(shù)運(yùn)行時(shí),實(shí)參_arguments被賦值
var _arguments = [];
for(var i = 0; i < arguments.length; i++){
_arguments[i] = arguments[i];
}
//下面執(zhí)行函數(shù)體
eval(fn_body);
}
}
替換成:
function _Function(){//獲得的形參列表為數(shù)組:_args
var _args = [];
for(var i = 0; i < arguments.length - 1; i++){
var obj = {};
obj['key'] = arguments[i];
obj[arguments[i]] = undefined;
_args.push(obj);
}
//this._argu = _args;
var fn_body = arguments[arguments.length - 1];
//下面的方法獲取實(shí)參_arguments,這里_arguments實(shí)現(xiàn)為一個(gè)數(shù)組,而非arguments對(duì)象
this.exec = function(){
//函數(shù)運(yùn)行時(shí),實(shí)參_arguments被賦值
var _arguments = [];
for(var i = 0; i < arguments.length; i++){
_arguments[i] = arguments[i];
}
//在運(yùn)行開(kāi)始就判斷關(guān)聯(lián)信息
for(var j = 0; j < Math.min(_arguments.length,_args.length); j++){
_args[j]["link"] = true;
}
//下面執(zhí)行函數(shù)體
eval(fn_body);
}
}
上面按理來(lái)說(shuō),關(guān)聯(lián)應(yīng)該是把兩者指向同一個(gè)對(duì)象,可是我只需要分析例子,沒(méi)打算做得那么精細(xì),所以是在函數(shù)體里面用if語(yǔ)句判斷的 。
把例子中fn_2換成對(duì)應(yīng)的形式就是:
// function fn_2(x){
// var x = 3;
// console.log(x,arguments[0]);
// arguments[0] = 2;
// console.log(x,arguments[0]);
// }
// fn_2(1)
//在fn_2body中,用_args[i]["link"] = true;來(lái)表示形參與實(shí)參相關(guān)聯(lián)
var fn_2body = ''+
'_args[0][_args[0]["key"]] = 3;'+
'if(_args[0]["link"]){ _arguments[0] = _args[0][_args[0]["key"]];}' +
'console.log(_args[0][_args[0]["key"]],_arguments[0]);'+
'_arguments[0] = 2;'+
'if(_args[0]["link"]){ _args[0][_args[0]["key"]] = _arguments[0]}' +
'console.log(_args[0][_args[0]["key"]],_arguments[0]);';
var fn_2 = new _Function('x',fn_2body);
fn_2.exec(1);
function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
}
fn()
顯然,兩者相互獨(dú)立:
x = 10,arguments[0] = 20;
推測(cè)一下:
function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
}
fn(1)
應(yīng)該都是輸出20,20
function fn(x){
arguments[0] = 20;
console.log(x,arguments[0])
}
fn(1)
應(yīng)該也都是輸出20,20
function fn(x){
arguments[0] = 20;
console.log(x,arguments[0])
}
fn()
應(yīng)該是undefined和20
原文來(lái)自cnblogs小西山子
今天看到別人的一個(gè)題目:
復(fù)制代碼 代碼如下:
function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
}
fn()
感覺(jué)自己對(duì)這也是一知半解,自己也可以試一下,于是就特地分析一下。
本想從語(yǔ)言的角度來(lái)分析,無(wú)奈功力不夠,只能粗淺的嘗試一下,于是稱之管中窺豹,還望大牛指正。
這是昨天寫(xiě)的,今天吃飯的時(shí)候又想了一下,想來(lái)想去感覺(jué)有些問(wèn)題還是說(shuō)得不靠譜,于是又試著修改了一下。
每一本js入門(mén)書(shū)籍都會(huì)提到,JS的函數(shù)內(nèi)部有一個(gè)Arguments的對(duì)象arguments,用來(lái)函數(shù)調(diào)用的時(shí)候?qū)嶋H傳入函數(shù)的參數(shù),fn.length保存形參的長(zhǎng)度。
這些對(duì)分析來(lái)說(shuō)略有用處,可是我想得到更多形參的信息,不知道有誰(shuí)有比較好的辦法,我暫時(shí)無(wú)解。
于是只能模擬了。
先不理會(huì)模擬,從實(shí)際問(wèn)題出發(fā):
復(fù)制代碼 代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<script type="text/javascript">
//形參中含有隱形的聲明var x = undefined
function fn(x){
console.log(x,arguments[0]);
arguments[0] = 2;
console.log(x,arguments[0]);
}
console.log('fn():');
fn();
//undefined , undefined
//undefined , 2
console.log('fn(1):');
fn(1);
//1,1
//2,2
重點(diǎn)關(guān)注后面兩個(gè)函數(shù)(fn_1,fn_2)的執(zhí)行,在這里,我們直接重新聲明了形參對(duì)應(yīng)的x,看到網(wǎng)上有的人說(shuō)這是聲明的一個(gè)局部變量x。
也是,不過(guò)這個(gè)局部變量不是一般的局部變量,x直接關(guān)聯(lián)對(duì)應(yīng)的arguments,上面的實(shí)例中就是x關(guān)聯(lián)arguments[0];
所以我猜測(cè)這個(gè)賦值的流程應(yīng)該是
1、函數(shù)定義的時(shí)候,聲明了形參,如果函數(shù)體內(nèi)有相同名稱的局部變量,則忽略此聲明。同時(shí)函數(shù)體內(nèi)同時(shí)會(huì)有一個(gè)對(duì)象arguments;
(亂入一句:個(gè)人以為arguments當(dāng)初不定義成數(shù)組的一個(gè)考慮是否是因?yàn)樵诤瘮?shù)定義內(nèi)無(wú)法確定實(shí)際參數(shù)的個(gè)數(shù)[運(yùn)行時(shí)動(dòng)態(tài)確定],那么要么這個(gè)數(shù)組無(wú)限大,要么數(shù)組一取值就越界)。
回到正題:
對(duì)于fn_2,初始化形參相當(dāng)于var x;(此時(shí)x沒(méi)有賦值,默認(rèn)為undefined,賦值是在語(yǔ)句執(zhí)行的時(shí)候賦值的)
所以如果可以這么寫(xiě)的話,fn_2就應(yīng)該是這樣:
復(fù)制代碼 代碼如下:
function fn_2(var x){
x = 3;
console.log(x,arguments[0]);
arguments[0] = 2;
console.log(x,arguments[0]);
}
2、函數(shù)語(yǔ)法檢測(cè)通過(guò),執(zhí)行的時(shí)候,函數(shù)內(nèi)部的arguments對(duì)象一開(kāi)始就得到賦值,賦值完畢后,函數(shù)體內(nèi)的語(yǔ)句開(kāi)始執(zhí)行。
下面的一段表述是我自己想的,不知道正確不正確(特別是關(guān)聯(lián)的說(shuō)法):
復(fù)制代碼 代碼如下:
一旦發(fā)現(xiàn)形參(對(duì)應(yīng)的變量)被賦值,那么會(huì)去尋找arguments對(duì)應(yīng)的項(xiàng),如果發(fā)現(xiàn)了arguments對(duì)應(yīng)的項(xiàng),那么設(shè)置形參與arguments對(duì)應(yīng)項(xiàng)的關(guān)聯(lián)。如果沒(méi)有發(fā)現(xiàn)arguments里面對(duì)應(yīng)的項(xiàng)(undefined),那么形參和arguments還是保持獨(dú)立。這里尋找的是arguments在函數(shù)運(yùn)行開(kāi)始的一個(gè)快照。反過(guò)來(lái)arguments賦值也是一樣。
上面的刪除的部分是昨天的,紅字部分是寫(xiě)到一半的時(shí)候發(fā)現(xiàn)有問(wèn)題加上去的。今天回過(guò)神來(lái),昨天為什么要傻逼的想到快照呢,這個(gè)不就是函數(shù)開(kāi)始運(yùn)行時(shí)直接
判斷關(guān)聯(lián)么?于是改了一下表述:
復(fù)制代碼 代碼如下:
在函數(shù)開(kāi)始執(zhí)行時(shí),設(shè)置形參與arguments的關(guān)聯(lián)信息。如果形參與對(duì)應(yīng)的arguments里面能找到對(duì)應(yīng)的項(xiàng)(均為undefined),那么兩者關(guān)聯(lián)。后面不論怎么處理,都不會(huì)改變整個(gè)函數(shù)體內(nèi)的關(guān)聯(lián)信息。
于是后面的實(shí)例說(shuō)明的說(shuō)法也要改變:
回到例子,fn_2函數(shù)語(yǔ)法檢測(cè)通過(guò),從第二步開(kāi)始執(zhí)行:
不帶參數(shù)的情況
復(fù)制代碼 代碼如下:
fn_2();
function fn_2(x){//arguments賦值完成,由于沒(méi)有實(shí)參,于是arguments參數(shù)列表為空。同時(shí)判斷關(guān)聯(lián)信息,顯然形參有,arguments空,兩者相互獨(dú)立,以后都不會(huì)再關(guān)聯(lián)
var x = 3;//x賦值為3,x與arguments[0]相互獨(dú)立,arguments[0]還是為undefined
console.log(x,arguments[0]);//打印x=3,arguments[0]為undefined
arguments[0] = 2;//arguments被賦值,x與arguments[0]相互獨(dú)立。因此x=3不改變
console.log(x,arguments[0]);//打印x = 3,arguments[0]=2
}
帶參數(shù)的情況
復(fù)制代碼 代碼如下:
帶參數(shù)的情況 fn_2(1);
function fn_2(x){//arguments賦值完成,arguments[0]=1。同時(shí)形參x有值,兩者相關(guān)聯(lián),永結(jié)同心。
var x = 3;//x賦值為3,x與arguments[0]關(guān)聯(lián),于是arguments[0]被賦值為3,。
console.log(x,arguments[0]);//打印x=3,arguments[0] = 3
arguments[0] = 2;//arguments[0]被賦值2,由于x與arguments[0]已經(jīng)關(guān)聯(lián)到一起,于是x同時(shí)改變
console.log(x,arguments[0]);//打印x = 2,arguments[0]=2
}
反過(guò)來(lái)應(yīng)該也是一樣的:
不帶參數(shù)
復(fù)制代碼 代碼如下:
fn_2();
function fn_2(x){//不關(guān)聯(lián)
arguments[0] = 2;//找不到對(duì)應(yīng)的x(undefined),相互獨(dú)立
console.log(x,arguments[0]);//undefined,2
x = 3;//相互獨(dú)立,快照。雖然arguments動(dòng)態(tài)添加了,老死不相往來(lái),所以依舊失敗
console.log(x,arguments[0]);//3,2
}
帶參數(shù)
復(fù)制代碼 代碼如下:
fn_2(1);
function fn_2(x){
arguments[0] = 2;//關(guān)聯(lián)
console.log(x,arguments[0]);//2,2
x = 3;//關(guān)聯(lián)
console.log(x,arguments[0]);//3,3
}
由于我們只有一個(gè)形參,可能說(shuō)服力不夠,現(xiàn)在增加到兩個(gè)。
只有一個(gè)實(shí)參的情況:
復(fù)制代碼 代碼如下:
fn_2(1);
function fn_2(x,y){ //arguments賦值完成,arguments[0]=1,arguments[1]=undefined,因此只有x與arguments[0]關(guān)聯(lián),y與arguments[1]老死不往來(lái)
console.log(x,y,arguments[0],arguments[1]); //1,undefined,1,undefined
var x = 3; //x賦值為3,x與arguments[0]關(guān)聯(lián),于是arguments[0]被賦值為3。
console.log(x,y,arguments[0],arguments[1]); //3,undefined,3,undefined
var y = 4; //y賦值為3,y與arguments[1]相互獨(dú)立,arguments[1]還是為undefined
console.log(x,y,arguments[0],arguments[1]); //3,4,3,undefined
arguments[0] = 2; //arguments[0]被賦值2,由于x與arguments[0]已經(jīng)關(guān)聯(lián)到一起,于是x同時(shí)改變
console.log(x,y,arguments[0],arguments[1]); //2,4,2,undefined
arguments[1] = 5; //arguments[1]被賦值5,y與arguments[1]相互獨(dú)立,于是y還是保持為4
console.log(x,y,arguments[0],arguments[1]); //x=2,y=4,arguments[0]=2,arguments[1]=5
}
有兩個(gè)實(shí)參的情況:
復(fù)制代碼 代碼如下:
fn_3(1,6);
function fn_3(x,y){ //arguments賦值完成,arguments[0]=1,arguments[1]=6,x與arguments[0],y與arguments[1]都相互關(guān)聯(lián)
console.log(x,y,arguments[0],arguments[1]); //1,6,1,6
var x = 3; //x賦值為3,x與arguments[0]關(guān)聯(lián),于是arguments[0]被賦值為3。
console.log(x,y,arguments[0],arguments[1]); //3,6,3,6
var y = 4; //y賦值為3,y與arguments[1]關(guān)聯(lián),于是arguments[1]被賦值為4。
console.log(x,y,arguments[0],arguments[1]); //3,4,3,4
arguments[0] = 2; //arguments[0]被賦值2,由于x與arguments[0]已經(jīng)關(guān)聯(lián)到一起,于是x同時(shí)改變
console.log(x,y,arguments[0],arguments[1]); //2,4,2,4
arguments[1] = 5; //arguments[1]被賦值5,由于y與arguments[1]已經(jīng)關(guān)聯(lián)到一起,于是y同時(shí)改變
console.log(x,y,arguments[0],arguments[1]); //x=2,y=5,arguments[0]=2,arguments[1]=5
}
以上全部是推測(cè),因?yàn)閷?shí)際中沒(méi)有辦法形參的信息,所以我按照推測(cè)寫(xiě)了一個(gè)小測(cè)試:
下面的也改了:
復(fù)制代碼 代碼如下:
function _Function(){//獲得的形參列表為數(shù)組:_args
var _args = [];
for(var i = 0; i < arguments.length - 1; i++){
var obj = {};
obj['key'] = arguments[i];
obj[arguments[i]] = undefined;
_args.push(obj);
}
//this._argu = _args;
var fn_body = arguments[arguments.length - 1];
//下面的方法獲取實(shí)參_arguments,這里_arguments實(shí)現(xiàn)為一個(gè)數(shù)組,而非arguments對(duì)象
this.exec = function(){
//函數(shù)運(yùn)行時(shí),實(shí)參_arguments被賦值
var _arguments = [];
for(var i = 0; i < arguments.length; i++){
_arguments[i] = arguments[i];
}
//下面執(zhí)行函數(shù)體
eval(fn_body);
}
}
替換成:
復(fù)制代碼 代碼如下:
function _Function(){//獲得的形參列表為數(shù)組:_args
var _args = [];
for(var i = 0; i < arguments.length - 1; i++){
var obj = {};
obj['key'] = arguments[i];
obj[arguments[i]] = undefined;
_args.push(obj);
}
//this._argu = _args;
var fn_body = arguments[arguments.length - 1];
//下面的方法獲取實(shí)參_arguments,這里_arguments實(shí)現(xiàn)為一個(gè)數(shù)組,而非arguments對(duì)象
this.exec = function(){
//函數(shù)運(yùn)行時(shí),實(shí)參_arguments被賦值
var _arguments = [];
for(var i = 0; i < arguments.length; i++){
_arguments[i] = arguments[i];
}
//在運(yùn)行開(kāi)始就判斷關(guān)聯(lián)信息
for(var j = 0; j < Math.min(_arguments.length,_args.length); j++){
_args[j]["link"] = true;
}
//下面執(zhí)行函數(shù)體
eval(fn_body);
}
}
上面按理來(lái)說(shuō),關(guān)聯(lián)應(yīng)該是把兩者指向同一個(gè)對(duì)象,可是我只需要分析例子,沒(méi)打算做得那么精細(xì),所以是在函數(shù)體里面用if語(yǔ)句判斷的 。
把例子中fn_2換成對(duì)應(yīng)的形式就是:
復(fù)制代碼 代碼如下:
// function fn_2(x){
// var x = 3;
// console.log(x,arguments[0]);
// arguments[0] = 2;
// console.log(x,arguments[0]);
// }
// fn_2(1)
//在fn_2body中,用_args[i]["link"] = true;來(lái)表示形參與實(shí)參相關(guān)聯(lián)
var fn_2body = ''+
'_args[0][_args[0]["key"]] = 3;'+
'if(_args[0]["link"]){ _arguments[0] = _args[0][_args[0]["key"]];}' +
'console.log(_args[0][_args[0]["key"]],_arguments[0]);'+
'_arguments[0] = 2;'+
'if(_args[0]["link"]){ _args[0][_args[0]["key"]] = _arguments[0]}' +
'console.log(_args[0][_args[0]["key"]],_arguments[0]);';
var fn_2 = new _Function('x',fn_2body);
fn_2.exec(1);
畫(huà)了一張圖來(lái)表示實(shí)例與改寫(xiě)函數(shù)兩者的關(guān)系,順便也改了一下:
復(fù)制代碼 代碼如下:
function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
}
fn()
顯然,兩者相互獨(dú)立:
x = 10,arguments[0] = 20;
推測(cè)一下:
復(fù)制代碼 代碼如下:
function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
}
fn(1)
應(yīng)該都是輸出20,20
復(fù)制代碼 代碼如下:
function fn(x){
arguments[0] = 20;
console.log(x,arguments[0])
}
fn(1)
應(yīng)該也都是輸出20,20
復(fù)制代碼 代碼如下:
function fn(x){
arguments[0] = 20;
console.log(x,arguments[0])
}
fn()
應(yīng)該是undefined和20
原文來(lái)自cnblogs小西山子
相關(guān)文章
Javascript添加監(jiān)聽(tīng)與刪除監(jiān)聽(tīng)用法詳解
這篇文章主要介紹了Javascript添加監(jiān)聽(tīng)與刪除監(jiān)聽(tīng)用法,較為詳細(xì)的分析了javascript原理與用法,并補(bǔ)充說(shuō)明了事件監(jiān)聽(tīng)的兼容性問(wèn)題,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-12-12js 獲取瀏覽器版本以此來(lái)調(diào)整CSS的樣式
判斷當(dāng)前使用的是那個(gè)瀏覽器及瀏覽器的那個(gè)版本,根據(jù)瀏覽器版本來(lái)調(diào)整CSS的樣式,下面是獲取當(dāng)前瀏覽器的代碼,需要的朋友可以參考下2014-06-06實(shí)現(xiàn)js保留小數(shù)點(diǎn)后N位的代碼
最近在做項(xiàng)目的時(shí)候,遇到要保留小數(shù)點(diǎn)后N位的問(wèn)題,經(jīng)過(guò)一番思索,最終完成了,這里記錄一下,下次需要直接就能拉出來(lái)用了2014-11-11JavaScript實(shí)現(xiàn)數(shù)字前補(bǔ)“0”的五種方法示例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)數(shù)字前補(bǔ)“0”的五種方法,結(jié)合具體實(shí)例形式分析了javascript數(shù)字前補(bǔ)0的相關(guān)操作技巧,涉及javascript字符串遍歷、迭代、截取、構(gòu)造等操作,需要的朋友可以參考下2019-01-01