多数情况下,this 指向调用它所在方法
的那个对象
。
解释:谁调的函数,this 就指向谁。如果没有指定谁调用,就指向全局对象。严格模式下指向undefined
this
是在调用时决定的;闭包
是在书写时决定的。
不管方法被书写在哪个位置,它的 this 只会跟着它的调用方走
好消息!在三种特殊的函数中,无论是否是严格模式,this 会 100% 指向 window:
setTimeout 和 setInterval 以及里面的函数,都会首先被交付到全局对象手上
构造函数里面的 this 会绑定到我们 new 出来的这个对象上
严格模式下的情况稍有不同。
普通函数是指 函数声明 或者 函数表达式,不包括箭头函数。
在非严格模式下,this 会指向全局变量(window 或 global)
严格模式下,如果没有指定对象,this 就是 undefined
'use strict';function commonFn() {console.log(this);}commonFn(); // undefinedwindow.commonFn(); // window
即在 全局作用域
下执行的函数或代码段里的 this。
不管它是否处于严格模式下,它的 this 都指向全局变量。
'use strict';console.log(this); // windowsetTimeout(function () {console.log(this); // window});
经过试验,所有的高阶函数中,this 指向的都是全局对象。
如:Array.prototype.map
,Array.prototype.filter
,Array.prototype.reduce
,
箭头函数是 es6 提供的新的函数形式,和普通函数的区别有这些:
箭头函数的 this 会在书写阶段(即声明位置)就绑定到它父作用域的 this 上
改变 this 指向的三个方法:
call
,apply
,bind
举例:
var obj = 'ruims';function commonfn() {console.log(this);}commonfn(); // windowcommonfn.call(obj); // 'ruims'
首先屡一下这三个方法的共同点。
call/apply 的核心实现原理是:
call 方法模拟
Function.prototype.myCall = function (context, ...args) {// ...args是rest参数,表示剩余参数,args是剩余参数数组args = args || [];// step1: 把函数挂到目标对象上(这里的 this 就是我们要改造的的那个函数)context.func = this;// step2: 执行函数context.func(...args);// step3: 执行完成删除delete context.func;};
apply 方法模拟并且有返回
Function.prototype.myApply = function (context, args) {args = args || [];context.func = this;var res = context.func(...args);delete context.func;return res;};
bind 方法模拟
bind 与 apply/call 一样都能改变函数 this 指向,但 bind 并不会立即执行函数,而是返回一个绑定了 this 的新函数,
在调用 bind 时可以先传递部分参数,在调用返回的 bound 时可以补全剩余参数。
Function.prototype.myBind = function (context, ...args) {var self = this;// args 等于 [].slice.call(arguments, 1);args = args || [];var bound = function (...params) {return self.apply(context, args.concat(params));};return bound;};