1. 程式人生 > >你不知道的javaScript筆記(2)

你不知道的javaScript筆記(2)

是否 foreach 函數 嚴格模式 console spa new 簡單的 否則

this和對象原型

this是一個很特別的關鍵字,被自動定義在所有函數的作用域中

// foo.count 0,字面理解是錯誤的

function foo(num) {

console.log("foo:"+ num);

this.count++;

}

foo.count = 0;

var i;

for(i=0;i<10;i++){

if(i>5){

foo(i)

}

}

console.log(foo.count) //0

          

// 使用詞法作用域解決問題

function foo(num) {

console.log("foo:"+ num);

data.count++;

}

var data = {

count:0

};

var i;

for(i=0;i<10;i++){

if(i>5){

foo(i)

}

}

console.log(data.count); // 4

// foo標識符來替代this來引用函數對象,回避了this 的問題,完全依賴於變量foo的詞法作用域。

function foo(num) {

console.log("foo:"+ num);

foo.count++;

}

foo.count = 0

var i;

for(i=0;i<10;i++){

if(i>5){

foo(i)

}

}

console.log(foo.count) //4

//強制this 指向foo函數對象

function foo(num) {

console.log("foo:"+num);

this.count++

}

foo.count = 0;

var i;

for(i=0; i< 10; i++){

if(i>5){

foo.call(foo,i);

}

}

console.log(foo.count) //4

this是在運行是 綁定的,並不是在編寫時綁定的,它的上下文取決於函數調用時的各種條件,this的綁定和和函數聲明的位置沒有任何關系,只取決於函數調用的方式。

this全面解析

調用棧與調用位置

function baz(){

//當前調用棧是:baz

// 因此,當前的調用中位置是全局作用域

console.log("baz");

bar(); // <--bar的調用位置

}

function bar(){

//當前的調用棧是: baz-> bar

// 因此,當前調用位置在baz

console.log("bar);

foo(); // <-- foo 的調用位置

}

function foo(){

//當前的調用棧是: baz-> bar->foo

// 因此,當前調用位置在bar

console.log("foo");

}

baz(); // <-- baz 的調用位置

只有運行在非strict mode 下,默認綁定才能綁定到全局對象。

對象屬性引用鏈中只有最頂層或者說最後一層灰影響調用位置。

function foo() {

console.log(this.a);

}

var obj2 = {

a: 42,

foo:foo

};

var obj1 = {

a:2,

obj2: obj2

};

obj1.obj2.foo(); // 42

硬綁定的典型應用場景就是創建一個包裹函數,傳入所有的函數並返回接收到的所有的值。

function foo(something){

console.log(this.a,something);

return this.a + something;

};

var obj = {

a:2

};

var bar = function() {

return foo.apply(obj,arguments);

};

var b = bar(3) ; // 2 3

console.log(b) // 5

另一種方法是創建一個i可以重復使用的輔助函數

function foo(something){

console.log(this.a, something);

return this.a + something;

}

// 簡單的輔助綁定函數

function bind(fn,obj){

return function(){

return fn.apply(obj,arguments);

};

}

var obj = {

a:2

}

var bar = bind(foo,obj);

var b = bar(3); // 2 3

console.log(b) // 5

ES5 中提供了內置的方法 Function.prototype.bind, bind(..) 會返回一個硬編碼的新函數,它會

把參數設置為this的上下文並調用原始函數。

function foo(something){

console.log(this.a, something);

return this.a + something;

}

var obj = {

a:2

}

var bar = foo.bind(obj);

var b = bar(3); // 3 5

console.log(b) // 5

API 調用的 上下文

function foo(el){

console.log(el,this.id);

}

var obj = {

id: "awesome‘

}

// 調用 foo(..)時把this 綁定到obj

[1,2,3].forEach(foo,obj);

// 1 awesome 2 awesome 3 awesome

new可以影響函數調用時this 綁定行為的方法。

function foo(a){

this.a = a;

}

var bar = new foo(2);

console.log(bar.a); // 2

判斷this

1.函數是否在new 中調用(new 綁定)? 如果是的話this 綁定的是新創建的對象。

var bar = new foo();

2.函數是否通過call , apply (顯示綁定) 或者硬綁定調用? 如果是的話,this的綁定時指定的對象。

va bar = foo.call(obj2)

3.函數是否在某個上下文對象中調用(隱式綁定) ? 如果是的話,this 的綁定時在那個上下文。

var bar = obj1.foo()

4.如果都不是的話,使用默認綁定。如果在嚴格模式下,就綁定到undefined,否則綁定到全局對象上。

var bar = foo();

軟綁定

function foo(){

console.log("name:" + this.name);

}

var obj = {name: "obj"},

obj2 = {name: "obj2"},

obj3 = {name: "obj3"},

obj3 = {name: "obj3"};

var foo0BJ = foo.softBind(obj);

foo0BJ(); // name:obj

obj2.foo = foo.softBind(obj);

obj2.foo(); // name:obj3 <--看!

setTimeout(obj2.foo,10);

// name:obj <--- 應用了軟綁定

你不知道的javaScript筆記(2)