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

相关推荐
霸王蟹21 分钟前
带你手写React中的useReducer函数。(底层实现)
前端·javascript·笔记·学习·react.js·typescript·前端框架
托尼沙滩裤26 分钟前
【Vue3】实现屏幕共享惊艳亮相
前端·javascript·vue.js
啃火龙果的兔子31 分钟前
前端八股文-vue篇
前端·javascript·vue.js
Mintopia1 小时前
计算机图形学环境贴图(Environment Mapping)教学指南
前端·javascript·计算机图形学
shenyan~1 小时前
关于 WASM: WASM + JS 混合逆向流程
开发语言·javascript·wasm
Mintopia1 小时前
Three.js 高级纹理(Advanced Textures):超越基础,打造沉浸式 3D 世界
前端·javascript·three.js
玄玄子1 小时前
JS Promise
前端·javascript·程序员
Raink老师1 小时前
7. TypeScript接口
javascript·typescript
Thanks_ks1 小时前
探索现代 Web 开发:从 HTML5 到 Vue.js 的全栈之旅
javascript·vue.js·css3·html5·前端开发·web 开发·全栈实战
GIS之路1 小时前
OpenLayers 获取地图状态
前端·javascript·html