谈谈对this对象的理解?以及this指向的问题

this对象的定义

  • this 是指函数被调用时的上下文
  • this对象 代表了当前执行上下文主体对象
  • this指向最后一次调用这个方法的对象
  • this的值 并不是在函数定义时确定的,而是在函数被调用时确定的

this的指向

在实际开发中,this 的指向一般可以通过四种调用模式来判断:

1. 函数调用(默认绑定)

当一个函数不是一个对象的属性时,直接作为函数来调用时,this的值在非严格模式下全局对象(在浏览器环境中为window),在严格模式下为undefined

kotlin 复制代码
function fun() {
  console.log(this);
}
 
fun();  // 非严格模式下输出window,严格模式下输出undefined

var name = 'Jenny';
function person() {
    return this.name;
}
console.log(person()); // Jenny
2. 方法调用(隐式绑定)
  • 如果一个函数作为一个对象的方法来调用时,this 指向这个对象(实例一)

  • 若函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this 指向的也只是它上一级的对象(实例二)

  • 函数this 永远指向的是最后调用它的对象(实例三)

javascript 复制代码
// 实例一
function test() {
    console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m(); // 1


var obj = {
    a:10,
    b:{
    fn:function(){
        console.log(this.a); // undefined
        }
    }
}

obj.b.fn(); 


var obj = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); // undefined
            console.log(this); // window
        }
    }
}

var j = obj.b.fn;
j();
/*
此时 this 指向的是 window,这里的大家需要记住,this 永远指向的是最后调用它的对象,虽
然fn 是对象b 的方法,但是 fn 赋值给 j时候并没有执行,所以最终指向  window */
3. 构造函数调用(new 绑定)
  • 如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象(实例一)
  • new过程中遇到return一个对象时,此时this指向为return的对象(实例二)
  • new过程中遇到return一个简单类型或者null时,此时this仍然指向实例对象(实例三)
javascript 复制代码
// 实例一
function Test(value) {
  this.value = value;
}
var obj = new Test(8);
console.log(obj.value);  // 输出8

// 实例二
function fn(){
    this.user = 'xxx';
    return {};
}

var a = new fn();
console.log(a.user); // undefined

// 实例三
function fn(){
    this.user = 'xxx';
    return 1; // 或者 return null
}

var a = new fn;
console.log(a.user); //xxx
4. apply 、 call 和 bind 调用模式(显示绑定)
call、apply、bind的共同点:
  • 这三个方法都可以显示的指定调用函数的 this 指向
  • 它们的第一个参数就表示改变后调用这个函数的对象即this指向的就是第一个参数
  • 第一个参数是null或者undefined时,默认指向window(浏览器)
call、apply、bind的区别:
  • call方法接收两个参数,第一个参数是this的值,第二个参数是传递给函数的参数,以逗号分隔,参数一次性传入。改变this指向后原函数会立即执行,此方法只临时改变this指向一次

  • apply方法也接收两个参数,第一个参数是this的值(为null或者undefined时,默认指向window(浏览器)),第二个参数一个数组或类数组对象,改变this指向后原函数会立即执行,此方法只临时改变this指向一次

  • bind方法创建一个新的函数,当这个新函数被调用时,bind的第一个参数将作为它运行时的this,参数可分多次传入。改变this指向不会立即执行,而是返回一个永久改变this指向的函数

scss 复制代码
function fn(...args){
    console.log(this,args);
}

let obj = {
    myname:"xxx"
}
// apply
fn.apply(obj,[1,2]); 

// call
fn.call(obj,1,2);

const bindFn = fn.bind(obj); // this指向obj
// bind不会理解执行需要执行一次
bindFn(1,2) // this指向obj

fn() // this指向window
小结
  • 在全局的环境下this是指向window
  • 普通函数调用直接调用中的this 会指向 window
  • 严格模式下this会指向 undefined
  • 自执行函数 this 指向 window
  • 定时器中的 this 指向 window
  • 在对象里调用的this,指向调用函数的那个对象
  • 在构造函数以及类中的this,构造函数配合 new 使用, 而 new 关键字会将构造函数中的 this 指向实例化对象,所以构造函数中的 this 指向 当前实例化的对象
  • 方法中的this谁调用就指向谁。
  • 箭头函数没有自己的 this,箭头函数的this在定义的时候,会继承自外层第一个普通函数的this

箭头函数

  • 在ES6中的箭头函数语法,让我们在书写时就能确定this的指向编译时绑定)(实例一)

箭头函数的坑:

  • 绑定监听事件(实例二)
  • 原型上添加方法(实例三)
  • 箭头函数不能作为构建函数
javascript 复制代码
// 实例一
const obj = {
    sayThis: () => {
        console.log(this);
    }
};

obj.sayThis(); // window
// 因为JavaScript没有块作用域,所以在定义sayThis时,里面的this就绑定到window了

const globalSay = obj.sayThis;
globalSay(); // window

// 实例二
const button = document.getElementById('mngb');
button.addEventListener('click', ()=> {
    console.log(this === window) // true
    this.innerHTML = 'clicked button'
})

// 实例三
Cat.prototype.sayName = () => {
    console.log(this === window) //true
    return this.name
}

const cat = new Cat('mm');
cat.sayName()

this的绑定规则

根据不同的使用场合,this 有不同的值,主要分为下面几种情况:

  • 默认绑定
  • 隐式绑定
  • new绑定
  • 显示绑定

优先级

new绑定优先级>显示绑定优先级>隐式绑定优先级>默认绑定优先级>

使用this 时常见的问题以及解决方案

  • 常见问题 ‌:在回调函数、定时器或事件处理程序中,由于this的绑定规则,可能会导致this指向不正确。
  • 解决方案‌:
  • 使用箭头函数来避免this绑定问题。
  • 使用.bind(this)显式绑定this
  • 在函数外部保存this的引用,如const self = this;

通过理解和掌握this在不同上下文中的行为,以及callapplybind方法的使用,你可以更有效地控制JavaScript中的this指向,从而编写出更加健壮和可维护的代码。

相关推荐
前端小巷子12 分钟前
Cookie与Session:Web开发中的身份验证与数据存储
前端·javascript·面试
成遇1 小时前
Eslint基础使用
javascript·typescript·es6
前端小趴菜056 小时前
React-React.memo-props比较机制
前端·javascript·react.js
RadiumAg9 小时前
记一道有趣的面试题
前端·javascript
yangzhi_emo9 小时前
ES6笔记2
开发语言·前端·javascript
yanlele9 小时前
我用爬虫抓取了 25 年 5 月掘金热门面试文章
前端·javascript·面试
烛阴11 小时前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
初遇你时动了情11 小时前
腾讯地图 vue3 使用 封装 地图组件
javascript·vue.js·腾讯地图
dssxyz11 小时前
uniapp打包微信小程序主包过大问题_uniapp 微信小程序时主包太大和vendor.js过大
javascript·微信小程序·uni-app
ohMyGod_12314 小时前
React16,17,18,19新特性更新对比
前端·javascript·react.js