js中this指向问题
在js中,this关键字的指向是一个比较重要的概念,它的值取决于函数的调用方式。
全局状态下
//全局状态下 this指向windows
console.log("this", this);
console.log("this===windows", this === window);
在函数中
// 在函数中 this指向windows
function text() {
console.log("在函数中this", this);
}
text();
函数作为对象的方法被调用
// 函数作为对象的方法被调用 this指向该方法的对象
const info = {
name: "info",
infoFunc: function () {
console.log("info对象中this指向该对象", this, this.name);
},
};
构造函数中
// 构造函数中 this指向新创建的对象
function Person(name) {
this.name = name;
console.log("构造函数", this);
}
const person = new Person("zs");
函数嵌套函数,使用变量存储this,箭头函数
const info2 = {
name: "alice",
// 函数嵌套函数 this 指向windows
info2Fun2: function () {
function fun2() {
console.log("函数嵌套函数中", this);
}
fun2();
},
info2Fun3: function () {
//为了解决函数嵌套函数this指向windows的问题
//将当前方法中的 this 值(也就是 info2 对象)存储到 _this 变量中
var _this = this;
function fun3() {
console.log("使用_this存储this", _this);
}
fun3();
},
// 使用箭头函数也可以解决函数嵌套函数
info2Fun4: function () {
// 箭头函数没有this,向上寻找则为info2对象的this
const fun2 = () => {
console.log("info2Func2方法中的fun2函数", this);
};
fun2();
},
};
info2.info2Fun2();
info2.info2Fun3();
info2.info2Fun4();
显示修改this指向
在 JavaScript 中,apply、call 和 bind 是 Function 对象的三个重要方法,它们主要用于改变函数内部 this 的指向,同时还能在调用函数时传递参数
call
function greet(message) {
console.log(`${message}, ${this.name}`);
}
const person2 = { name: "John" };
greet(person2, "Hello1111");
greet.call(person2, "Hello");
不加call为什么是[object Object],
普通函数调用的时候 this指向全局对象,在这个调用里面,把person2作为参数传递给greet函数,但函数内部不指向perosn2。greet函数只接收一个参数,当调用的时候,message被赋值为perosn2,第二个参数就被忽略了。全局对象的name为空字符串,同时message是person2对象,对象默认的字符串表示形式是 [object Object] 所以打印结果为[object Object]
console.log('window.name',window.name,typeof(window.name));
加call
call方法第一个参数就是要绑定给this的对象,后续参数依次传递给被调用的函数,当调用的时候,this被显示地绑定到person2对象上,message被赋值为Hello
call方法支持传入多个参数,以逗号隔开
function greet(message,message2) {
console.log(`${message}, ${this.name},${message2}`);
}
const person2 = { name: "John" };
greet.call(person2, "Hello","aaaaa");
apply
apply与call类似,第一个参数都是指定函数执行时this的值,第二个参数也是传递数据用的,区别是它是以数组元素的形式传入的,多个参数则传入多个元素。当不确定参数数量的时候使用apply更方便。
greet.apply(person2,['BBBBBBBB','CCCCC'])
bind
bind与call和aplly类似,第一个参数也是指定函数执行时this的值,区别是call和apply会立即执行,而bind会返回一个新的函数供后续使用
const greet2=greet.bind(person2,'DDDDDD','EEEEE');
greet2();
const greet3=greet.bind(person2,'FFFFF','GGGGGG');
greet3();
vue中的this
选项式API
在生命周期,methods,computed,watch中,this都指向组件实例
<template>
<div class="box">
<div @click="addNum">A:{{ num }}</div>
<div @click="addNum2">B:{{ num }}</div>
<div @click="addNum2">C:{{ num2}}</div>
</div>
</template>
<script>
export default {
data(){
return {
num:10
}
},
computed:{
num2(){
console.log('computed',this);
return this.num;
}
},
watch:{
num(newvalue,oldvalue){
console.log('watch',this);
console.log(newvalue,oldvalue);
}
},
created(){
console.log('created中this',this);
},
mounted(){
console.log('mounted中this',this);
},
methods:{
addNum(){
console.log('methods',this);
this.num++;
},
addNum2:()=>{
console.log('箭头函数',this);
}
}
}
</script>
组合式API
组合式 API 鼓励将逻辑封装在函数中,这些函数可以在setup函数中调用。通过这种方式,逻辑更加模块化,作用域更加清晰。不再依赖this来访问实例的属性和方法,而是直接从返回的对象中解构出所需的变量和函数。
END