谈谈对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指向,从而编写出更加健壮和可维护的代码。

相关推荐
jane_xing几秒前
Next.js + SQLite 项目 Docker 生产环境部署方案
javascript·docker·sqlite
Billy Qin40 分钟前
Rollup详解
前端·javascript·rollup
前端小菜鸟一枚s1 小时前
`ConstantPositionProperty` 的使用与应用
前端·javascript·cesium
JohnsonXin1 小时前
怎么使用vue3实现一个优雅的不定高虚拟列表
前端·javascript·css·html5
东望1 小时前
写代码不规范,同事两行泪 😭(工程化如何让团队协作更高效)
javascript·前端工程化
用户837701408811 小时前
前端实现个人信息脱敏(手机号、身份证号、姓名、邮箱)JavaScript代码示例
javascript
前端小菜鸟一枚s1 小时前
`ConstantProperty` 的使用与应用
前端·javascript·cesium
Neverthe1ess1 小时前
创新项目实训开发日志1
前端·javascript·vue.js·vue
阿里云云原生1 小时前
如何使用通义灵码学习JavaScript和DOM
前端·javascript
疯狂平头哥2 小时前
canvas签字+html2canvas将dom保存为图片避坑指南
前端·javascript