介绍js中this

定义

this是js的一个关键字,this指向当前执行上下文中的对象。在不同的上下文中,this的值会有所不同。

不同上下文的this指向

全局上下文

在全局执行上下文中,this 指向全局对象。在浏览器中,这个全局对象是 window,在Node.js中则是 global

console.log(this); // 在浏览器中输出 Window 对象
函数上下文 

在普通函数内,this 默认为全局对象(在严格模式下为 undefined)。但是如果通过对象调用一个方法,this 会指向那个对象。

  function showThis() {
    console.log(this);
  }
  showThis();// 在浏览器中输出Window对象或undefined

  const obj = {
    name: 'Tom',
    fn1: function () {
      console.log(this.name);
    }
  };
  obj.fn1(); // 输出'Tom'
构造函数上下文

当使用 new 关键字调用构造函数时,this 指向新创建的实例对象。

function Person(name) {
  this.name = name;
}
const p = new Person('Alice');
console.log(p.name); // 输出'Alice'
箭头函数的上下文

箭头函数不会创建自己的 this 值,它会从外部上下文中继承 this

const obj = {
  value: 42,
  getValue: function() {
    return () => this.value; // 这里的 this 继承自 getValue 的上下文
  }
};
const func = obj.getValue();
console.log(func()); // 输出 42
 function foo() {
   this.value = '111';
   (() => {
     console.log(this.value); // 此处的this继承自foo的实例  
   })();
 }

 new foo(); // 输出:111
DOM元素上下文

当在 DOM 元素的上下文中使用 this 时,this 都指向触发事件的 DOM 元素。

const button = document.getElementById('myButton');
button.addEventListener('click', function() {
    console.log(this); // 输出按钮元素
});
<button onclick="console.log(this)">Click me</button> 
类的上下文

在 ES6 类中,构造函数和类方法中的 this 关键字指向类的实例。因此,类的方法在被实例化对象调用时,this 会指向该实例。

class Animal {
    constructor(name) {
        this.name = name;
    }
    action() {
        console.log(`${this.name} is sleeping.`);
    }
}
const cat = new Animal('Cat');
cat.action(); // 输出 'Cat is sleeping.'
bind、apply和call的上下文

bind(), call() 和 apply() 都是 JavaScript 中函数对象的方法,它们用于操作函数并改变其行为。bind() 函数用于创建一个新的函数,这个新函数绑定指定的上下文(this);call() 和 apply() 则分别用于立即调用一个函数,并允许设置特定的this值以及传递给函数的具体参数列表。简而言之,bind() 创建绑定,call() 调用并设置this,apply() 同样调用但接受数组作为参数。

bind
基础用法
  function introduce(greeting, punctuation1, punctuation2) {
      console.log(greeting + ', ' + this.name + punctuation1 + punctuation2);
    }

    const person = { name: 'Bob' };

    // 使用 bind 预设第一个参数
    const boundIntroduce = introduce.bind(person, 'Hi');

    // 在调用时再传递剩余参数
    boundIntroduce('!', '!!'); // 输出: Hi, Bob!!!
多次bind绑定
// 多重绑定-this值、参数顺序
// 严格模式,防止this被封装到包装对象中
"use strict"; 
function log(...args) {
  console.log(this, ...args);
}

const boundLog = log.bind('new value', 1, 2);
const newBoundLog = boundLog.bind('new new value', 3, 4,5);
newBoundLog(7, 8);
// new value 1 2 3 4 5 7 8
类数组对象转换为真正的数组
// 定义一个示例函数,里面使用 arguments 作为类数组对象
function exampleFunction() {
    // 获取类数组对象 arguments
    const args = arguments;

    // 输出类数组对象
    console.log('类数组对象 arguments:', args);

    // 使用 Array.prototype.slice.call() 将类数组对象转换为真正的数组
    const argsArray = Array.prototype.slice.call(args);

    // 输出转换后的数组
    console.log('转换后的数组:', argsArray);
}

// 调用示例函数,传入一些参数
exampleFunction(1, 'two', true, { key: 'value' });

以下方法确保了 Array.prototype.slicethis 上下文在调用时始终指向 Array.prototype.slice,使得可以更灵活地使用这个方法。 

function exampleFunction() {
    const unboundSlice = Array.prototype.slice;
    const slice = Function.prototype.call.bind(unboundSlice);

    // 获取类数组对象
    const args = arguments;

    // 使用绑定的 slice 函数将类数组对象转换为数组
    const argsArray = slice(args);

    console.log('类数组对象 arguments:', args);
    console.log('转换后的数组:', argsArray);
}

// 调用示例函数,传入一些参数
exampleFunction(1, 'two', true, { key: 'value' });
apply
基础用法
function greet(greeting, punctuation) {
    return greeting + ', ' + this.name + punctuation;
}

const person = { name: 'Alice' };

// 使用 apply 调用 greet 函数
const message = greet.apply(person, ['Hello', '!']);
console.log(message); // 输出: "Hello, Alice!"
数组方法应用于类数组对象
const arrayLike = { 0: 'hello', 1: 'world', length: 2 };
const result = Array.prototype.join.apply(arrayLike, [', ']);
console.log(result); // 输出: "hello, world"
实现替代数组展开语法

 一般而言,fn.apply(null, args) 等同于使用参数展开语法的 fn(...args),只是在前者的情况下,args 期望是类数组对象,而在后者的情况下,args 期望是可迭代对象。

//调用
const numbers = [5, 6, 2, 3,7];
const max = Math.max.apply(null, numbers);
const min = Math.min.apply(null, numbers);
console.log('max, min', max, min);
//参数展开

const array = ["a", "b"];
const elements = [0, 1,2];
array.push.apply(array, elements);
console.info(array);

array.push(...elements);
console.log(array);

//批量添加数组元素
const array = ["a", "b"];
const elements = [0, 1,2];
array.push.apply(array, elements);
console.info(array);

array.push(...elements);
console.log(array);
call
基础用法
function introduce(greeting, punctuation) {
    console.log(greeting + ', ' + this.name + punctuation);
}

const person = { name: 'Alice' };

// 使用 call 传递所有参数
introduce.call(person, 'Hello', '!'); // 输出: Hello, Alice!
call与bind的区别

1、call立即执行,bind返回一个新函数

2、call一次性传递所有参数,bind不一定一次性传递所有参数,可以第一次传递部分参数,剩余参数传给返回值

call与apply的区别

call使用逗号分隔的参数进行传递,apply则是将所有参数放入一个数组进行传递

异步操作上下文
setTimeout/setInterval 的上下文

setTimeout和setInterval中的回调函数默认指向undefined或全局对象

setTimeout(() => {
  console.log(this)
}, 0)

setInterval(() => {
  console.log(this)
}, 1000)
Promise的上下文

Promise的this也默认指向undefined或全局对象

const promise = new Promise(function(resolve, reject) {
  console.log(this); //undefined (严格模式) 或者是全局对象 (非严格模式)
  resolve('完成');
});

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AAA`

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值