最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

javascript管中窺豹 形參與實參淺析

 更新時間:2011年12月17日 23:47:18   作者:  
本想從語言的角度來分析,無奈功力不夠,只能粗淺的嘗試一下,于是稱之管中窺豹,還望大牛指正
引子:
今天看到別人的一個題目:
復制代碼 代碼如下:

function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
}
fn()

感覺自己對這也是一知半解,自己也可以試一下,于是就特地分析一下。
本想從語言的角度來分析,無奈功力不夠,只能粗淺的嘗試一下,于是稱之管中窺豹,還望大牛指正。
這是昨天寫的,今天吃飯的時候又想了一下,想來想去感覺有些問題還是說得不靠譜,于是又試著修改了一下。
每一本js入門書籍都會提到,JS的函數(shù)內(nèi)部有一個Arguments的對象arguments,用來函數(shù)調(diào)用的時候?qū)嶋H傳入函數(shù)的參數(shù),fn.length保存形參的長度。
這些對分析來說略有用處,可是我想得到更多形參的信息,不知道有誰有比較好的辦法,我暫時無解。
于是只能模擬了。
先不理會模擬,從實際問題出發(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

重點關(guān)注后面兩個函數(shù)(fn_1,fn_2)的執(zhí)行,在這里,我們直接重新聲明了形參對應的x,看到網(wǎng)上有的人說這是聲明的一個局部變量x。
也是,不過這個局部變量不是一般的局部變量,x直接關(guān)聯(lián)對應的arguments,上面的實例中就是x關(guān)聯(lián)arguments[0];
所以我猜測這個賦值的流程應該是
1、函數(shù)定義的時候,聲明了形參,如果函數(shù)體內(nèi)有相同名稱的局部變量,則忽略此聲明。同時函數(shù)體內(nèi)同時會有一個對象arguments;
(亂入一句:個人以為arguments當初不定義成數(shù)組的一個考慮是否是因為在函數(shù)定義內(nèi)無法確定實際參數(shù)的個數(shù)[運行時動態(tài)確定],那么要么這個數(shù)組無限大,要么數(shù)組一取值就越界)。
回到正題:
對于fn_2,初始化形參相當于var x;(此時x沒有賦值,默認為undefined,賦值是在語句執(zhí)行的時候賦值的)
所以如果可以這么寫的話,fn_2就應該是這樣:
復制代碼 代碼如下:

function fn_2(var x){
x = 3;
console.log(x,arguments[0]);
arguments[0] = 2;
console.log(x,arguments[0]);
}

2、函數(shù)語法檢測通過,執(zhí)行的時候,函數(shù)內(nèi)部的arguments對象一開始就得到賦值,賦值完畢后,函數(shù)體內(nèi)的語句開始執(zhí)行。
下面的一段表述是我自己想的,不知道正確不正確(特別是關(guān)聯(lián)的說法):
復制代碼 代碼如下:

一旦發(fā)現(xiàn)形參(對應的變量)被賦值,那么會去尋找arguments對應的項,如果發(fā)現(xiàn)了arguments對應的項,那么設置形參與arguments對應項的關(guān)聯(lián)。如果沒有發(fā)現(xiàn)arguments里面對應的項(undefined),那么形參和arguments還是保持獨立。這里尋找的是arguments在函數(shù)運行開始的一個快照。反過來arguments賦值也是一樣。

上面的刪除的部分是昨天的,紅字部分是寫到一半的時候發(fā)現(xiàn)有問題加上去的。今天回過神來,昨天為什么要傻逼的想到快照呢,這個不就是函數(shù)開始運行時直接
判斷關(guān)聯(lián)么?于是改了一下表述:
復制代碼 代碼如下:

在函數(shù)開始執(zhí)行時,設置形參與arguments的關(guān)聯(lián)信息。如果形參與對應的arguments里面能找到對應的項(均為undefined),那么兩者關(guān)聯(lián)。后面不論怎么處理,都不會改變整個函數(shù)體內(nèi)的關(guān)聯(lián)信息。

于是后面的實例說明的說法也要改變:
回到例子,fn_2函數(shù)語法檢測通過,從第二步開始執(zhí)行:
不帶參數(shù)的情況
復制代碼 代碼如下:

fn_2();
function fn_2(x){//arguments賦值完成,由于沒有實參,于是arguments參數(shù)列表為空。同時判斷關(guān)聯(lián)信息,顯然形參有,arguments空,兩者相互獨立,以后都不會再關(guān)聯(lián)
var x = 3;//x賦值為3,x與arguments[0]相互獨立,arguments[0]還是為undefined
console.log(x,arguments[0]);//打印x=3,arguments[0]為undefined
arguments[0] = 2;//arguments被賦值,x與arguments[0]相互獨立。因此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。同時形參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同時改變
console.log(x,arguments[0]);//打印x = 2,arguments[0]=2
}

反過來應該也是一樣的:
不帶參數(shù)
復制代碼 代碼如下:

fn_2();
function fn_2(x){//不關(guān)聯(lián)
arguments[0] = 2;//找不到對應的x(undefined),相互獨立
console.log(x,arguments[0]);//undefined,2
x = 3;//相互獨立,快照。雖然arguments動態(tà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
}

由于我們只有一個形參,可能說服力不夠,現(xiàn)在增加到兩個。
只有一個實參的情況:
復制代碼 代碼如下:

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]老死不往來
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]相互獨立,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同時改變
console.log(x,y,arguments[0],arguments[1]); //2,4,2,undefined
arguments[1] = 5; //arguments[1]被賦值5,y與arguments[1]相互獨立,于是y還是保持為4
console.log(x,y,arguments[0],arguments[1]); //x=2,y=4,arguments[0]=2,arguments[1]=5
}

有兩個實參的情況:
復制代碼 代碼如下:

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同時改變
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同時改變
console.log(x,y,arguments[0],arguments[1]); //x=2,y=5,arguments[0]=2,arguments[1]=5
}

以上全部是推測,因為實際中沒有辦法形參的信息,所以我按照推測寫了一個小測試:
下面的也改了:
復制代碼 代碼如下:

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];
//下面的方法獲取實參_arguments,這里_arguments實現(xiàn)為一個數(shù)組,而非arguments對象
this.exec = function(){
//函數(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];
//下面的方法獲取實參_arguments,這里_arguments實現(xiàn)為一個數(shù)組,而非arguments對象
this.exec = function(){
//函數(shù)運行時,實參_arguments被賦值
var _arguments = [];
for(var i = 0; i < arguments.length; i++){
_arguments[i] = arguments[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);
}
}

上面按理來說,關(guān)聯(lián)應該是把兩者指向同一個對象,可是我只需要分析例子,沒打算做得那么精細,所以是在函數(shù)體里面用if語句判斷的 。
把例子中fn_2換成對應的形式就是:
復制代碼 代碼如下:

// 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;來表示形參與實參相關(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);

畫了一張圖來表示實例與改寫函數(shù)兩者的關(guān)系,順便也改了一下:

回到文章開頭的例子:
復制代碼 代碼如下:

function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
}
fn()

顯然,兩者相互獨立:
x = 10,arguments[0] = 20;
推測一下:
復制代碼 代碼如下:

function fn(x){
x = 10;
arguments[0] = 20;
console.log(x,arguments[0])
}
fn(1)

應該都是輸出20,20
復制代碼 代碼如下:

function fn(x){
arguments[0] = 20;
console.log(x,arguments[0])
}
fn(1)

應該也都是輸出20,20
復制代碼 代碼如下:

function fn(x){
arguments[0] = 20;
console.log(x,arguments[0])
}
fn()

應該是undefined和20
原文來自cnblogs小西山子

相關(guān)文章

  • JavaScript創(chuàng)建對象的幾種方式及關(guān)于this指向問題

    JavaScript創(chuàng)建對象的幾種方式及關(guān)于this指向問題

    這篇文章主要介紹了JavaScript創(chuàng)建對象的幾種方式及關(guān)于this指向問題,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值。需要的小伙伴可以參考一下
    2022-07-07
  • javascript滾輪事件基礎實例講解(37)

    javascript滾輪事件基礎實例講解(37)

    這篇文章主要為大家詳細介紹了javascript滾輪事件基礎實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • javascript前端埋點上報的幾種方式

    javascript前端埋點上報的幾種方式

    本文將介紹前端埋點上報的幾種常見方式,并詳細闡述如何在項目中運用這些方式進行數(shù)據(jù)上報,以幫助開發(fā)者更好地進行數(shù)據(jù)收集和分析,感興趣的可以了解一下
    2023-11-11
  • js實現(xiàn)小球在頁面規(guī)定的區(qū)域運動

    js實現(xiàn)小球在頁面規(guī)定的區(qū)域運動

    這篇文章主要為大家詳細介紹了js控制小球在規(guī)定范圍運動,碰到邊界就改變運動方向,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • js設置控件的隱藏與顯示的兩種方法

    js設置控件的隱藏與顯示的兩種方法

    js設置控件的隱藏與顯示,設置控件style的display和visibility屬性就可以了,下面有個示例,需要的朋友可以參考下
    2014-08-08
  • 淺析JS中回調(diào)函數(shù)的使用

    淺析JS中回調(diào)函數(shù)的使用

    在JavaScript中,回調(diào)函數(shù)是一種常見的編程模式,用于處理異步操作和事件處理,這篇文章主要為大家介紹了回調(diào)函數(shù)的使用場景和注意事項,需要的可以參考下
    2023-08-08
  • uni-app使用uni-download和uni.saveFile下載保存文件遇到的問題及解決方法

    uni-app使用uni-download和uni.saveFile下載保存文件遇到的問題及解決方法

    這篇文章主要給大家介紹了關(guān)于uni-app使用uni-download和uni.saveFile下載保存文件遇到的問題及解決方法的相關(guān)資料,文中給出了詳細的代碼示例,需要的朋友可以參考下
    2024-01-01
  • JS中的6種打斷點的方式實例總結(jié)

    JS中的6種打斷點的方式實例總結(jié)

    斷點調(diào)試是啥?難不難? 斷點調(diào)試其實并不是多么復雜的一件事,簡單的理解無外呼就是打開瀏覽器,打開sources找到js文件,在行號上點一下罷了,下面這篇文章主要給大家介紹了關(guān)于JS中6種打斷點方式的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • javascript下利用arguments實現(xiàn)string.format函數(shù)

    javascript下利用arguments實現(xiàn)string.format函數(shù)

    sitepoint上看到Andrew Tetlaw在08年寫的文章arguments: A JavaScript Oddity,閱讀之后,除了對arguments溫故知新一遍以外,印象最深刻的還是Andrew的第一個函數(shù)實現(xiàn)的string.format功能。
    2010-08-08
  • JavaScript字符串常用的方法

    JavaScript字符串常用的方法

    這篇文章主要介紹了JavaScript字符串常用的方法 的相關(guān)資料,需要的朋友可以參考下
    2016-03-03

最新評論

天镇县| 长白| 崇阳县| 嘉祥县| 罗江县| 贵南县| 辽阳市| 防城港市| 海淀区| 来宾市| 敖汉旗| 稷山县| 盐津县| 山阳县| 汤原县| 和田市| 南康市| 巴林左旗| 全椒县| 尼玛县| 清丰县| 丘北县| 安顺市| 巴彦淖尔市| 衡东县| 怀仁县| 富民县| 安仁县| 宜良县| 土默特右旗| 哈密市| 巢湖市| 福海县| 宁安市| 富裕县| 舒城县| 措勤县| 芜湖市| 太原市| 长汀县| 皮山县|