是夜,想着考量下小黃毛近期的JavaScript進階如何了,鑑於近期一直在接觸Vue 2.0,索性就圍繞this編寫了個代碼片斷,javascript
給其一個測量,畢竟寫js的程序員都知道,JavaScript的函數調用時會隱性的接收到兩個附加的參數:this和arguments。java
/** * this */ var ajaxThis = (function() { global.a = 2; function fn(b) { this.b = b; console.log(this.a); } var obj = { a : 4, fn : fn }; fn();// 題1 obj.fn(); // 題2 fn.call(obj); // 題3 fn.call(null);// 題4 fn.apply(obj);// 題5 fn.apply(null);// 題6 var fnInstance = new fn(8); console.log(fnInstance.b);// 題7 })();
注:這些題倒不難,只要你把握好JavaScript中的this到底指向誰,那麼就問題不大。程序員
題1:2ajax
題2:4編程
題3:4數組
題4:2app
題5:4函數
題6:2this
題7:undefinedspa
8
不要好奇,第7題的確是輸出兩個值
先說些閒話,當你對JavaScript接觸使用的多了,就能感覺到它的方面之處,同時也可以避開它的缺點,發揚其優勢。
在解析答案以前,先來說解一下到底如何判斷this的取值吧。
其實,this的值取決於調用的模式。
調用模式?那都有哪些調用模式呢?
總的來講,JavaScript的函數調用總共有4種模式,是的,你沒聽錯,就是4種!!!
哪4種?
• 方法調用模式
• 普通函數調用模式
• 構造器調用模式
• apply/call調用模式
而針對這四種調用模式,參數this的取值會有所差別:
• 方法調用模式
何爲方法調用?固然泛指針對對象來講的了。該種調用模式說明,函數在某個明確的上下文對象中調用時,this綁定的是這個上下文對象。
e g. 題2的 obj.fn(); // 調用的對象是obj,因此this綁定的就是obj,因此fn()內部console.log(this.a)輸出的即是obj.a,即爲4
• 普通函數調用模式
普通函數調用?指的即是直接調用函數。這種調用模式,默認狀況下,若是函數是被直接調用的,則this綁定到全局對象;
若是在嚴格模式下(即 'use strict'),就綁定到undefined。
e g. 題1中的 fn(); // 由於沒有指明調用方,同時又是非嚴格模式,因此,fn()函數內部的this綁定到全局對象,因此this.a的值爲global.a,即爲2
• 構造器調用模式
構造器調用模式?這個應該都不陌生吧?!固然指的是經過new操做符來調用的函數啦!在這裏有點相似於面向對象編程的概念,構造器函數內部的this固然
綁定到這個新建立的對象了。這種調用模式,指的即是:若是函數經過new操做符調用,this綁定的是新建立的對象。
e g. 題7中的 var fnInstance = new fn(8); // 由於是經過new操做符調用的fn函數,因此this指向當前新建立的對象,然而這個對象沒有a這個屬性,因此輸出undefined
console.log(fnInstance.b); // 然而由於給fn函數傳入了值8,因此……
• apply/call調用模式
apply/call又是什麼鬼?我先來解說它們的用法吧!
a) apply()和call()方法的第一個參數都是要調用函數的對象。用apply()和call()調用函數時,函數內的this屬性老是引用這個參數;
b) call()函數剩餘參數是傳遞給要調用的函數的值,它們的數量能夠是任意的;
c) apply()方法和call()方法相似,只不過它只接收兩個參數,除了調用者以外,它的第二個參數是一個帶下標的集合(好比數組,但也能夠不是數據),
apply()方法把這個集合中的元素做爲參數傳遞給調用的函數。
OK,如今從新回到主題:該種調用模式,this又指的是誰?細心的你可能已經注意到,上面介紹他們的用法是,已經提到函數內的this屬性老是引用第一個參數,
也就是調用函數的對象。也就是說,函數經過apply/call調用,this綁定的是指定的對象,然而,若是把null/undefined做爲this的綁定對象傳入apply/call,
在調用時會被忽略,實際應用的是默認綁定規則。
e g. fn.call(obj); // 題3,答案爲console.log(obj.a),即爲4
fn.call(null);// 題4 ,由於null被忽略,答案爲console.log(global.a),即爲2
fn.apply(obj);// 題5 ,答案爲console.log(obj.a),即爲4
fn.apply(null);// 題6 ,由於null被忽略,答案爲console.log(global.a),即爲2
好了,就總結到這裏。小黃毛,你懂了嗎?