js 函數做用域與this 的指向實例

函數的定義分爲2種,(1)直接定義-window 下,內部定義;(2)對象的方法(或對象原型的方法),下面的函數fn1與fn2 是直接定義的函數,
doFunction是對象定義的方法,這2種狀況使用name時 name來自相應的域javascript

var name = 'window下的name<br/>';
var resultCon;
function fn1() {
    resultCon.innerHTML += name;
}

function MyObj() {
    var name = 'MyObj下的name<br/>';
    this.doFunction = function() {
        resultCon.innerHTML += name;
    };
}


window.onload = function() {
    resultCon = document.getElementById('result');
    //定義了局部的name變量跟全局的var name = "window 下的name <br/ >";是兩個不一樣的變量,也就是說這個局部的name變量不會覆蓋全局的變量,若是去掉var則會覆蓋全局name變量的值
    var name = "onload下的name<br/>";
    var fn2 = function() {
        resultCon.innerHTML += name;
    };
    fn1();//輸出window下的name,窗口加載完定義些變量後執行fn1,此時fn1裏面的name是全局的
    fn2();//onload下的name,因爲定義了name在onload下的局部變量
    var obj = new MyObj();
    obj.doFunction();//MyObj下的name ,實例化構造函數,在函數內部從新定義了name,全部會顯示MyObj下的name
};
代碼輸出結果:
window下的name
onload下的name
MyObj下的name

對於直接定義的函數。this指向windowjava

var name = 'window下的name<br/>';
var resultCon;
function fn1() {
    resultCon.innerHTML += this.name;//直接定義的函數this指向window
}

function MyObj() {
    this.name = 'MyObj下的name<br/>';//或者var name = 'MyObj下的name<br/>';
    this.doFunction = function() {
        resultCon.innerHTML += this.name;
    };
}


window.onload = function() {
    resultCon = document.getElementById('result');
    var name = "onload下的name<br/>";
    var fn2 = function() {
        resultCon.innerHTML += this.name;// 直接定義的函數this指向window
    };
    fn1();//window下的name
    fn2();//window下的name
    var obj = new MyObj();
    obj.doFunction();//MyObj下的name
};
代碼輸出結果:
window下的name
window下的name
MyObj下的name

JS容易犯錯的this和做用域數組

var someuser = { 
    name: 'byvoid', 
    func: function() {
        console.log(this.name); 
    }
}; 
var foo = { 
    name: 'foobar'
};
 
someuser.func(); // 輸出 byvoid
 
foo.func = someuser.func; 
foo.func(); // 輸出 foobar
 
name = 'global';
func = someuser.func; 
func(); // 輸出 global

上面的解釋:上面定義了2個對象someuser 與foo 以及一個全局變量name = 'global';一個對象的方法能夠賦給另外一個對象的方法,可是一個對象的屬性值不會賦給另外一個對象全部foo.func(); // 輸出 foobar
var scope = 'top';
var f1 = function() { 
    console.log(scope);
};
f1(); // 輸出 top
var f2 = function() { 
    var scope = 'f2'; 
    f1();
};
f2(); // 輸出 top
上面解釋:靜態做用域的含義是函數做用域的嵌套關係由定義時決定而不是調用時決定,又稱爲詞法做用域,函數f1在查找變量定義時,在語法分析時就已經完成,而不須要等到f1被調用的時候纔開始
上面的例子若是增長var scope = 'top1';則f2(); // 輸出 top1,由於f2()調用前就已經肯定好語法分析scope = 'top1' 以下
var scope = 'top';
var f1 = function() { 
    console.log(scope);
};
f1(); // 輸出 top
var scope = 'top1';
var f2 = function() { 
    var scope = 'f2'; 
    f1();
};
f2(); // 輸出 top1
<script>
var scope="global";  
function t(){  
    console.log(scope);  //undefined 
    var scope="local"  
    console.log(scope);  //local 
}  
t();  
</script>

可是當去掉後面的 var scope="local" console.log(scope);驚奇的事情發生了
<script>
var a = "global";
function myFunction() {
	 console.log(a);  //global
} 
 myFunction();
</script>

//緣由是因爲變量提高拆解爲下面的就好理解了
    function t() {
        var scope;
        console.log(scope);
        scope = "local";
        console.log(scope);
    }
    t()
var name="global";    
if(true){    
    var name="local";    
    console.log(name)    
}    
console.log(name);  

所有輸出local由於if沒有做用域,因此在if裏面的var定義是從新定義了一個全局變量將前面的全局變量覆蓋了
<script>
name="lwy";  
function t(){  
    var name="tlwy";  
    function s(){  
        var name="slwy";  
        console.log(name);  
    }  
    function ss(){  
        console.log(name);  
    }  
    s();  //slwy
    ss(); // tlwy
}  
t();   
</script> 
當執行s時,將建立函數s的執行環境(調用對象),並將該對象置於鏈表開頭,而後將函數t的調用對象連接在以後,最後是全局對象。
而後從鏈表開頭尋找變量name,很明顯
name是"slwy"。
但執行ss()時,做用域鏈是: ss()->t()->window,因此name是」tlwy"
var myvar = "my value";

(function() {
  console.log(myvar); // undefined  由於下面從新定義了局部變量,而且會變量提高, 至關於在console.log(myvar) 以前var myvar 以下:
  var myvar = "local value";
})();

var myvar = "my value";
(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = "local value";
})();


var myvar = "my value";
(function() {
  console.log(myvar); // my value  
  
})();

爲建立的數組賦值 ide

function map() {
var a =	[0, 1, 2, 5, 10];  
 var result = []; // 建立一個新的數組
 var i;
  for (i = 0; i < a.length; i++)
    //var result = []; 不能放在此位置,由於每次循環時候result 都賦值爲空
    result[i] = a[i]+2;
	alert(result);
	console.log(result);// 數組2,3,4,7,12
  return result;

}
function outside(x) {
  function inside(y) {
    return x + y;
  }
  return inside;
}

fn_inside = outside(3); 
result = fn_inside(5); 
console.log(result ) //8

arguments的用法 函數

function myConcat(separator) {
   var result = "", // initialize list
       i;
   // iterate through arguments
   for (i = 1; i < arguments.length; i++) {
      result += arguments[i] + separator;
      console.log(separator;)
//separator 接受的是第一個參數,(separator,separator1)若這樣接受2個參數,separator形參接受的實參就是第一個參數,
   }
   return result;
}
你能夠給這個函數傳遞任意數量的參數,它會將各個參數鏈接成一個字符串「列表」:

// returns "red, orange, blue, "
myConcat(", ", "red", "orange", "blue");
var a = 20;
    var b = a;
    b = 30;
    console.log(a); //20
    var m = { a: 10, b: 20 };
    var n = m;
    n.a = 15;
    console.log(m.a); //15  對象是按引用訪問的
var a = 20;
var obj = {
    a: 10,
    c: this.a + 20,
    fn: function() {
        return this.a
    }
}
console.log(obj.c); //40  因爲c是屬性不是方法,此時this指向window
console.log(obj.fn()); //10
var anotherobj = obj.fn;
console.log(anotherobj()); //20
相關文章
相關標籤/搜索