js中this的指向
之前学习js时发现this比较难懂,找了一些文章来看,现在自己尝试写一下,看看自己是否真的懂了。
就我自己所理解的,this值存在于函数里面,一般对象是没有的;this的指向有几个规则。1.默认绑定;2.隐式绑定;3.显示绑定;4.new 绑定;
this的指向只有在运行时才能确定而不是定义时;
它们的优先级是:4 > 3 > 2 > 1
箭头函数有点特殊,后面会说到;
1.默认绑定
在没有其他规则下使用的就是默认绑定这个规则;一般指的是独立函数
function fn() {
console.log('默认绑定', this);
默认绑定下this指向的全局对象(window)
}
fn();
输出结果:

如果是严格模式下this是指向undefined
"use strict"; //严格模式
function fn() {
console.log('默认绑定', this);
}
fn();

2.隐式绑定
一般是指某个对象的方法
"use strict";
var name = 'sky';
function fn() {
console.log('隐式绑定', this.name);
}
const obj = {
name: 'blue',
sayName: fn
};
obj.sayName(); // 这里的函数作为对象的方法this指向的是调用这个方法的对象,即obj
输出结果:

如果有多层对象的,只有最后一层对象才会影响this的指向;如:obj.p.sayName(); // 影响this指向的是p这个对象。
var name = 'sky';
function fn() {
console.log('隐式绑定', this.name);
}
const pn = {
name: 'red',
sayName: fn,
}
const obj = {
name: 'blue',
p: pn,
};
obj.p.sayName();

有时会出现隐式绑定丢失;其实是被骗了,不存在所谓丢失
var name = 'sky';
function fn() {
console.log('隐式绑定', this.name);
}
const obj = {
name: 'blue',
sayName: fn,
};
var sayName = obj.sayName;
sayName();
输出结果:

this指向的全局变量,这个时候应用的默认绑定的规则,
var sayName = obj.sayName; // obj.sayName是把方法赋值给了sayName这个变量,这时sayName不再是某个对象的方法,而是一个独立的函数;
所以才说被骗;
3.显式绑定
是通过call(); apply(), bind()来改变函数this的指向
var name = 'sky';
function fn() {
console.log('显示绑定', this.name);
}
const obj = {
name: 'blue',
sayName: fn,
};
fn.apply(obj); // 手动把this指向到obj中, call()和apply()是改变的同时也调用了函数;bind()只是改变并没有调用,会返回一个改变后的函数;
显示绑定也会出现丢失,但是我觉得不算是一种丢失
var name = 'sky';
function fn() {
console.log('显示绑定', this.name);
}
const obj = {
name: 'blue',
sayName: fn,
};
var Hi = function(fn) {
fn();
}
Hi.call(obj, fn); // 搞不懂为什么这样也叫丢失,Hi函数就根本没有this,怎么改的了
4.new 绑定
js不同其他的语言,任何一个函数都可以使用new来调用,因此不存在构造函数,而是对函数的“构造调用”;
使用 new 来调用函数,会自动执行下面的操作
1.创建一个新对象
2.将构造函数的作用域赋值给新对象,即this指向这个新对象
3.执行构造函数中的代码
4.返回新对象
所以用 new 来调用这个函数时this就会绑定到这个新对象中
var name = 'sky';
function sayHi(name) {
this.name = name;
}
var t = new sayHi('tttt');
console.log(t.name);
输出结果: tttt
最后,说说箭头函数
1. 箭头函数自己本身是没有this的,它是继承外层代码块的this(我认为指的就是函数,一般的对象是没有this的)
2.不可以当作构造函数,所以不能使用new命令,不然会报错
3.不可以使用 arguments 对象,该对象在函数体内不存在,如果要用,可以使用rest参数代替
4.不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数
5. 箭头函数没有自己的this,所以不能用call, apply, bind
const obj = {
hi: function() {
console.log('普通函数', this)
return () => { console.log('箭头函数', this) };
},
};
var t = obj.hi();
t();
结果:
结果显示了箭头函数的this是继承上一层代码块的this;

浙公网安备 33010602011771号