JavaScript中的this

JavaScript中的this

// this是什么
// 全局环境中的this
// 函数中的this
// 方法中的this
// 事件中的函数中的this
// 构造函数中this
// call和apply
// bind
// 箭头函数中的this
// 严格模式下的一些状况数组

this是什么

js中的this关键字是包含它的函数做为方法被调用时所属的对象。浏览器

看似很抽象的一句话,但实际理解起来比较困难,咱们能够分3部分来理解它!
一、包含它的函数。二、做为方法被调用时。三、所属的对象。app

首先咱们先来看一下js中非严格模式下的this分别都是什么函数

全局环境中的this

在全局执行上下文中(在任何函数体外部)this 都指代全局对象。this

// 在浏览器中, window 对象同时也是全局对象:
console.log(this === window); // true

a = 37;
console.log(window.a); // 37

this.b = "MDN";
console.log(window.b)  // "MDN"
console.log(b)         // "MDN"

函数中的this

绝大多数状况下,函数的调用方式决定了this的值。prototype

在严格模式和非严格模式之间也会有一些差异。code

function f1(){
  return this;
}
//在浏览器中:
f1() === window;   //在浏览器中,全局对象是window

然而,在严格模式下,this将保持他进入执行上下文时的值,因此下面的this将会默认为undefined。对象

function f2(){
  "use strict"; // 这里是严格模式
  return this;
}

f2() === undefined; // true

自执行函数执行,方法中的this通常都是window继承

var obj = {
    fn: (function() {
        // this -> window
    })()
};

~function() {
    // this -> window
}()

方法中的this

咱们说定义在对象内的函数叫作方法,而这个方法执行的时候,它的this就是它的调用者事件

var obj = {
    fn: function () {
        console.log(this);
    }
};

obj.fn();

此时fn方法的调用者为obj,因此fn中的this就是obj对象;

但咱们把这个方法赋值给一个自由变量的时候

var f1 = obj.fn;

f1();

此时f1执行,实际是obj.fn执行,但f1的调用者其实是 window, window.f1() 因此fn中的this是window

下面再看一个例子,
咱们调用数组上的slice方法,

[].slice(); // this -> []

[].__proto__.slice(); // this -> [].__proto__

Array.prototype.slice();  // this -> Array.prototype

三种调用的slice方法是同样的,但调用的方式不一样,里面的this也不一样

事件中的函数中的this

给元素的某个事件绑定了一个方法,当事件触发,函数执行的时候,绑定的这个方法中的this通常是当前操做的这个DOM元素

'二般'状况下

IE6~8下,若是咱们使用DOM2事件绑定,方法执行的时候,里面的this不是当前元素,而是window

ele.attachEvent('onclick', function() {
    console.log(this);  // window
});

构造函数中的this

构造函数执行的时候,函数体中的this都是当前实例;

function Fn() {
    // this -> 当前Fn的实例
    // this.name 是给当前实例设置私有属性
    this.name = '1000phone'
}

var f = new Fn();

call和apply

当一个函数在其主体中使用 this 关键字时,能够经过使用函数继承自Function.prototype 的 call 或 apply 方法将 this 值绑定到调用中的特定对象。

var school = {name: '1000phone'};

function sum(num1, num2) {
    this.total = num1 + num2;
}

sum(20, 30); // this -> window

sum.call(school, 20, 30);

首先让 sum 中的this指向call方法中的第一个参数,而后执行sum这个函数

此时 sum 中的 this -> school num1 -> 20 num2 -> 30

参数位置是固定的,若是第一个参数不是 school

sum.call(20, 30);

这时候 sum 的this 是 20,num1 -> 30 num2 -> undefined

若是咱们一个参数都不传

sum.call();

sum 的 this -> window num1 = num2 = undefined

至关于 sum 直接执行,不传参

sum();

但若是第一个参数为null或者undefined
那么就表明没有this,函数中的this依然是window

apply语法与做用,和call相似,只有一个区别,apply传入一组参数

sum.call(school, 20, 30);

sum.apply(school, [20, 30]);

apply的语法要求写成一个数组,但实际和call同样,也是一项一项的给形参赋值的

~function () {
    console.log(this);
}.call(school);

此时 自执行函数中的this被call指向为 school

Array.prototype.slice.call(arguments);

此时slice方法执行的时候中的this将再也不是 Array.prototype,而是arguments

call和apply以前的规则,遇到call/apply时,都将以用户自主指向的this为主

bind

ECMAScript 5 引入了 Function.prototype.bind。调用f.bind(someObject)会建立一个与f具备相同函数体和做用域的函数,可是在这个新函数中,this将永久地被绑定到了bind的第一个参数,不管这个函数是如何被调用的。

var school = {name: '1000phone'};

function sum(num1, num2) {
    this.total = num1 + num2;
}

sum.call(school, 20, 30);

this -> school 而且执行sum

sum.bind(school, 20, 30);

虽然改变了this指向,但并无执行sum,它是预先处理this和实参,不会当即执行,

一般咱们让它在某个特定条件,才会被触发 IE6~8不兼容

例如咱们有个需求,一秒后执行sum,此时须要定时器,执行sum时,sum中this指向school,而且传参。

setTimeout(sum, 1000);

咱们一秒后执行sum函数

但此时sum中的this是window

setTimeout(sum.call(school, 20, 30), 1000);

此时实现了this的指向而且传了参数,但sum当即执行了,不是一秒后

setTimeout(function() {
    sum.call(school, 20, 30);
}, 1000);

咱们能够达到一秒后执行sum,this指向为shool,而且传参,执行,但代码并不理想,咱们能够使用bind预处理可以达到咱们的目的

setTimeout(sum.bind(school, 20, 30), 1000);

箭头函数中的this

var obj = {
    fn: function() {

        setTimeout(function() {
            // this -> window
        }, 1000);

        var that = this;
        setTimeout(function() {
            // that -> obj
        }, 1000);

        setTimeout(function() {
            // this -> obj
        }.bind(this), 1000);

        setTimeout(() => {
            // this -> obj
        }, 1000);
    }
};

在箭头函数中,this与封闭词法上下文的this保持一致,也就是说箭头函数中继承了词法做用域的this

严格模式下

非严格模式下,不明确执行主体,浏览器认为执行主体默认为window,因此this是window

严格模式下,执行主体不明确,this是undefined

'use strict'

~function(){
    // this -> undefined
}();

fn() // undefined

window.fn()  // window

fn.call() // undefined

fn.call(window) // window

fn.call(null) // null

fn.call(undefined) // undefined

apply同call

能够理解为含有this的函数的调用者。而且this和函数在哪执行的,以及定义的位置没有直接关系。

欢迎来喷!

相关文章
相关标签/搜索