1、左查詢:LHS 當執行a=2時,會進行左查詢
右查詢(非左查詢) RHS: 當執行 console.log( a ) 時,會進行非左查詢
當右查詢當時候沒找到變數會拋ReferenceError錯誤,如: console.log(a)
而左查詢沒有找到變數當時候會在全域性作用域中定義一個變數(非嚴格模式)
2、變數提升
變數宣告提升至作用域頂端
函式優先
函式表示式不會提升
3、閉包:
將內部函式傳遞到所在的詞法作用域以外,它都會持有對原始定義作用域的引用,形成閉包
只要將函式進行值傳遞,就會出現閉包。
經典問題:for (var i=1; i<=5; i++) {
setTimeout(() => {
console.log(i); // 6、6、6、6、6
}, 0);
}
解釋:函式作用域查詢全域性作用域的i,全域性作用域唯一當i此時為6
4、通過作用域可以實現程式碼模組化
var foo = (function(global){
function doSomething(){ ... }
return {
do:doSomething
}
})(window)
foo.do();
第二部分:this 和物件原型
1、this繫結
a、預設繫結window
b、隱式繫結:當函式引用有上下文物件時,this指向該物件
物件屬性引用鏈中只有最頂層或者說最後一層會影響呼叫位置
var obj1={ a:1, foo: foo, }
var obj2={ a:2, obj1: obj1, }
function foo(){ console.log(this.a) }
obj2.obj1.foo() // 1
隱式丟失:
1、var obj = { a:1, foo: foo, } ; var a = global;
function foo(){ console.log(this.a) }
var bar=obj.foo;
bar(); // global
2、function foo(){ console.log(this.a) }
function doFoo( fn ){ fn() }
var obj = { a:1, foo: foo }
doFoo( obj.foo ) // global
c、顯式繫結 call、apply
1、以上隱式丟失問題可以使用硬繫結解決
2、forEach的第二個引數,繫結this指向
function foo(el) { console.log( el, this.id ); } // 1 2 3
var obj = { id: "awesome" };
[1, 2, 3].forEach( foo, obj );
3、硬繫結的函式不能改變this指向
var obj={ a:1 }; var a=2;
function foo() { console.log(this.a); }
var bar = function() { foo.call( obj ); }
bar(); // 2
bar.call( window ); // 2
d、new繫結
通過new建立的this自動繫結上下文到該物件
1. 建立(或者說構造)一個全新的物件。
2. 這個新物件會被執行[[原型]]連線。
3. 這個新物件會繫結到函式呼叫的this。
4. 如果函式沒有返回其他物件,那麼new表示式中的函式呼叫會自動返回這個新物件。
更安全的this
var ø = Object.create( null );
var bar = foo.bind( ø, 2 );