// 彻底弄懂js里面的this
// *第一种情况*
// 全局作用域或者普通函数中this指向全局对象window
// 直接打印
console.log(this) // window
// function 声明函数
function a() {
console.log(this)
}
a(); // window
// function 声明函数然后赋值给变量
b = function bar() {
console.log(this)
}
b() // window
// 自动执行函数
(function () { console.log(htis) })() // window
// *第二种情况*
// 方法调用中的this到底指向谁
var person = {
run: function () {
console.log(this)
}
}
person.run() // person
// 事件绑定
var btn = document.querySelector("button")
btn.onclick = function () {
console.log(this) // btn
}
//事件监听
var btn = document.querySelector("button")
btn.addEventListener('click', function () {
console.log(this) // btn
})
//jquery的ajax
$.ajax({
self: this, //window
type: "get",
url: url,
async: true,
success: function (res) {
console.log(this) // this指向传入$.ajxa()中的对象
console.log(self) // window
}
});
//这里说明以下,将代码简写为$.ajax(obj) ,this指向obj,在obj中this指向window,因为success方法中,独享obj调用自己,所以this指向obj
//第三种 *在构造函数或者构造函数原型对象中this指向构造函数的实例*
//不使用new指向window
function Person (name) {
console.log(this) // window
this.name = name;
}
Person('inwe')
//使用new
function Person (name) {
this.name = name
console.log(this) //people
self = this
}
var people = new Person('iwen')
console.log(self === people) //true
//这里new改变了this指向,将this由window指向Person的实例对象people
// 一针见血式总结:
// 普通函数中的this:
// 1. this总是代表它的直接调用者(js的this是执行上下文), 例如 obj.func ,那么func中的this就是obj
// 2.在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window (约定俗成)
// 3.在严格模式下,没有直接调用者的函数中的this是 undefined
// 4.使用call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象
// 箭头函数中的this
// 箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this
var obj = {
say: function () {
setTimeout(function () {
console.log(this)
});
}
}
obj.say(); //window 因为调用的是setTimeout函数 而setTimeout函数是window的一个方法,所以this会指向window
// 如果想要在setTimeout/setInterval中使用这个对象的this引用呢?
// 用一个 变量提前把正确的 this引用保存 起来, 我们通常使用that = this, 或者 _this = this来保存我们需要的this指针!
var obj = {
func: function() {},
say: function () {
var that = this; //此时的this就是obj对象
setTimeout(function () {
console.log(this)
that.func()
});
}
}
obj.say();
// 我们也可以使用 func.bind(this) 给回调函数直接绑定宿主对象, bind绑定宿主对象后依然返回这个函数, 这是更好的做法
var obj = {
func: function() {},
say: function () {
// 此时的this就是obj对象
setTimeout(function () {
console.log(this)
this.func()
}.bind(this));
}
}
obj.say(); // obj
// 箭头函数中的this
var obj = {
say: function () {
setTimeout(() => {
console.log(this)
});
}
}
obj.say(); // obj
// 此时的 this继承自obj, 指的是定义它的对象obj, 而不是 window!
var obj = {
say: function () {
var f1 = () => {
console.log(this); // obj
setTimeout(() => {
console.log(this); // obj
})
}
f1();
}
}
obj.say()
// 因为f1定义时所处的函数 中的 this是指的 obj, setTimeout中的箭头函数this继承自f1, 所以不管有多层嵌套,都是 obj
var obj = {
say: function () {
var f1 = function () {
console.log(this); // window, f1调用时,没有宿主对象,默认是window
setTimeout(() => {
console.log(this); // window
})
};
f1();
}
}
obj.say()
// 结果: 都是 window,因为 箭头函数在定义的时候它所处的环境相当于是window, 所以在箭头函数内部的this函数window
var obj = {
say: function () {
'use strict';
var f1 = function () {
console.log(this); // undefined
setTimeout(() => {
console.log(this); // undefined
})
};
f1();
}
}
obj.say()
// 说明: 严格模式下,没有宿主调用的函数中的this是undefined!!!所以箭头函数中的也是undefined!
// 总结:
// 使用箭头函数,可以让我们解决一些在匿名函数中 this指向不正确的问题; 但是要注意在和普通函数混合的时候,this的指向可能是window !