此系列体验视频教程
点击观看:哔哩哔哩
this的各使用场合
1、全局环境
全局环境的this,指的是window
function fn() {
console.log(this === window);
}
fn() // true 本质原因是因为fn是由window对象调用的
window.fn() // true
console.log(this === window); // true
2、构造函数
构造函数中的this,指的是实例对象
function Fn(p) {
this.bar = p
console.log(this);
}
var obj1 = new Fn('obj1')
var obj2 = new Fn('obj2')
3、对象的方法
如果对象的方法里面包含this,this指向方法运行时所在的对象。将方法赋值给另一个对象的方法,就会改变this的指向
var obj1 = {
bar: 1,
fn: function () { // 这里保存的只是函数的地址,从作用域层面去考虑,跟放在全局没有什么区别。
console.log(this.bar);
}
}
obj1.fn() // 1
var obj2 = {
bar: 2
}
obj2.fn = obj1.fn // 将一个对象的方法作为地址赋值给另一个对象属性的话,那么调用此函数的对象一旦变化,this指向也就跟着变化了。
obj2.fn() // 2
var bar = 3
var fn = obj1.fn
fn() // 3
对象的方法中this的更复杂的情况
var bar = 1;
var obj = {
bar: 2,
fn: function () {
console.log(this.bar);
},
};
obj.fn(); // 2
(obj.fn = obj.fn)(); // 1
(obj.fn = function () {
console.log(this.bar);
})(); // 1
(function () {
console.log(this.bar);
})() // 1
// (true || obj.fn)(); // 报错
(false || obj.fn)(); // 1
(true && function () {
console.log(this.bar);
})(); // 1
(1, obj.fn)(); // 1
(1, function () {
console.log(this.bar);
})(); // 1
// 前面小括号最终返回的是一个函数的地址。后面再跟着小括号相当于直接调用此函数,并没有经过obj进行调用
// this不在对象第一层的情况,这时的this只是指向当前一层的对象,而不会继续指向更上一层。
var bar = 1
var obj = {
bar: 2,
o: {
bar: 3,
fn: function () {
console.log(this.bar);
}
}
}
obj.o.fn() // 3
var o = {
bar: 3,
fn: function () {
console.log(this.bar);
}
}
var obj = {
bar: 2,
o: o
};
(obj.o).fn() // 3
o.fn() // 3
var bar = 4
var fn = obj.o.fn // 赋值给全局变量,this依然指向全局
fn() // 4
// 所以一般为了保持this指向不变,都会连同调用函数的对象一起赋值给一个变量
var obj2 = obj.o
obj2.fn() // 3
this指向问题与解决
// 多层函数中的this的指向
var bar = 1
var obj1 = {
bar: 2,
fn1: function () {
console.log(this);
var that = this
var fn2 = function () { // 此立即执行函数是自己执行的,相当于在全局执行
console.log(that.bar);
}()
}
}
obj1.fn1() // 2
function temp() {
console.log(this.bar);
}
var bar = 1
var obj1 = {
bar: 2,
fn1: function () {
var fn2 = temp()
}
}
obj1.fn1() // 1
// 回调函数中this指向的问题
var obj2 = {
bar: 1,
fn: function () {
console.log(this.bar);
}
}
obj2.fn()
var bar = 2
function fn(f) {
f()
}
fn(obj2.fn) // 2
var obj3 = {
bar: 3,
fn: function (f) {
f()
}
}
obj3.fn(obj2.fn) // 2
如何固定this指向
var bar = 1
var obj = {
bar: 2
}
function fn() {
console.log(this.bar);
}
fn() // 1
fn.call(obj) // 2 call方法可以改变前面函数内部的this指向,使前面函数的this固定指向call函数的参数(对象)
// call方法的参数,应该是一个对象,如果参数为空、null、undefined,则默认传入全局对象window
fn.call()
fn.call(null)
fn.call(undefined)
fn.call(window)
// 回调函数中this指向的问题
var obj2 = {
bar: 1,
fn: function () {
console.log(this.bar);
}
}
obj2.fn() // 1
function fn2() {
obj2.fn.call(obj2)
}
var bar = 2
function fn(f) {
f()
}
fn(fn2) // 1
var obj3 = {
bar: 3,
fn: function (f) {
f()
}
}
obj3.fn(fn2) // 1
// 多层函数中的this的指向问题
var bar = 1
var obj1 = {
bar: 2,
fn1: function () {
var fn2 = function () {
console.log(this.bar);
}.call(obj1)
}
}
obj1.fn1() // 2
var obj = {
x: 1,
y: 2
}
function fn(x, y) {
console.log(x, y);
console.log(this.x + this.y + x + y);
}
fn.call(obj, 10, 16) // call还可以接收更多的参数,从第二个开始往后的参数都会传递到call前面的函数中,作为函数的参数。
// call转换类数组对象为数组
var obj = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
// var arr = ['a', 'b', 'c', 'd']
// var result = arr.slice()
// console.log(result);
var result = [].slice.call(obj)
console.log(result);