javascript不同凡響的this

一直以來都知道js的this讓初學者很困惑, 但因爲在學angularjs的時候潘老師早早的就教咱們寫代碼時先定義self = this , 而後經過操做self, 再以後學習angular又一直使用的箭頭函數, 因此js的this用起來和java的用起來並無什麼不一樣, 也就沒有認真的去學習js的this和其餘語言的到底獨特在那裏, 本週遇到了一個函數盡然不能使用箭頭函數, 又想起了這個問題, 就找了幾篇博客學了學。html

感覺一下

讓咱們先看幾段js代碼,並猜猜打印的是什麼java

下面的環境都爲chrome的控制檯, 即非嚴格模式(即不使用 use strict, 兩種模式下結果不相同)
// 例子1
function a(){
    name: 'yunzhi_a';
    console.log(this); //?
}
a();

// 例子2
var b = {
    name:"yunzhi_b",
    fn:function(){
        console.log(this)  //  ?
    }
}
b.fn();

// 例子3
var c = {
    name:"yunzhi_c",
    fn:function(){
        console.log(this); // ?
    }
}
window.c.fn();

// 例子4
var d = {
    name: 'yunzhi_d',
    o: {
        name: 'object',
        fn: function(){
            name: 'fn'
            console.log(this); // ?
        }
    }
}
var j = d.o.fn;
j();

是否是感受他們都差很少?
公佈答案以前, 先說一下this的使用的規則:angularjs

this的指向在函數定義的時候是肯定不了的,只有函數執行的時候才能肯定this到底指向誰實際上this的最終指向的是那個調用它的對象

例子的答案

例子1

image.png答案是Window,爲何呢?想一想上面的規則,**this的最終指向的是那個調用它的對象**,函數沒有調用對象,這時this將指向全局的window對象。chrome

例子2

第二個應該很簡單了,仍是上面的規則,此次是b調用的fn,因此嘛
image.pngapp

例子3

第三個呢,是誰調用的fnwindow嗎?再想一想
image.png
複習一下,this的最終指向的是那個調用它的對象, fn()是經過誰調用的,是c調用的,因此打這時的this指向的就是cide

例子4

看着和上面是差很少的對吧?因此答案就是o對吧?不對
image.png
再看看, 咱們調用的是j,雖然他是經過fn賦的值,但咱們確實調用的是前面沒有對象的j, 在例子1中已經說過了,此時會this會指向window函數

箭頭函數中的this

在使用箭頭函數時咱們不會遇到這種讓人暈乎的this指向問題post

箭頭函數保持它當前執行上下文的 詞法做用域不變,而普通函數則不會。換句話說,箭頭函數從包含它的詞法做用域中繼承到了 this的值。
var object = {
    data: [1,2,3],
    dataDouble: [1,2,3],
    double: function() {
        console.log("this inside of outerFn double()");
        console.log(this);    // object
        return this.data.map(function(item) {
            console.log(this);      // window
            return item * 2;
        });
    },
    doubleArrow: function() {
        console.log("this inside of outerFn doubleArrow()");
        console.log(this); // object
        return this.dataDouble.map(item => {
            console.log(this);      // objecgt
            return item * 2;
        });
    }
};
object.double();
object.doubleArrow();

是否是對map中的函數是誰調用的感到疑惑了?爲何是window
由於map中的函數是一個匿名函數,他並無調用者,想到上面的例子了吧,咱們能夠看一下map的基本實現學習

// Array.map polyfill
if (Array.prototype.map === undefined) {
    Array.prototype.map = function(fn) {
        var rv = [];
        for(var i=0, l=this.length; i<l; i++)
            rv.push(fn(this[i]));
        return rv;

直接使用的fn()this

嚴格模式對this的影響

this在嚴格模式下指向 undefined
大部分狀況下,開發者使用 this ,並不但願它指向全局 window 對象。嚴格模式幫咱們在使用 this關鍵詞時,儘可能少作搬起石頭砸本身腳的蠢事。

修改this指向

開發者能夠經過bindcall apply來主動控制this的指向,固然這裏再也不細說,有興趣能夠看這篇文章——JS中call、apply、bind使用指南,帶部分原理。

參考文章

完全理解js中this的指向,沒必要硬背。
[譯] 深刻淺出 JavaScript 關鍵詞 -- this