JavaScript中的this指向,call、apply、bind的简单实现

简介: JavaScript中的this指向,call、apply、bind的简单实现

原文合集地址如下,有需要的朋友可以关注

本文地址

JavaScript中的this

this是JavaScript中一个特殊关键字,用于指代当前执行上下文中的对象。它的难以理解之处就是值不是固定的,是再函数被调用时根据调用场景动态确定的,主要根据函数的调用方式来决定this指向的对象。this 的值在函数被调用时动态确定,以下是几种常见的情况:

  1. 全局上下文中:
    当在全局作用域中调用函数时,this 指向全局对象。在浏览器环境中,这个全局对象是 window 对象。

    console.log(this); // 在浏览器中,输出为 Window 对象
    
  2. 函数作为对象的方法:
    当函数作为对象的方法被调用时,this 指向调用该方法的对象。

    const obj = {
         
      property: 'value',
      printProperty: function() {
         
        console.log(this.property);
      }
    };
    
    obj.printProperty(); // 输出 'value'
    
  3. 构造函数中:
    在使用 new 关键字创建实例时,构造函数内部的 this 指向即将创建的新实例。

    function Person(name) {
         
      this.name = name;
    }
    
    const person = new Person('Alice');
    console.log(person.name); // 输出 'Alice'
    
  4. 显式绑定:
    使用call、apply、bind方法可以显式指定this的绑定对象。
    ``javascript function greet(message) { console.log(${message}, ${this.name}!`);
    }

const person = { name: 'Bob' };

greet.call(person, 'Hello'); // 输出 'Hello, Bob!'

5. **箭头函数:**
箭头函数不绑定this,它会捕获外层作用域的this值作为自己的this。

```javascript
const obj = {
  method: function() {
    const arrowFunc = () => {
      console.log(this === obj);
    };
    arrowFunc();
  }
};

obj.method(); // 输出 true
  1. class中的this:
    类中的this默认指向类的实例对象。
    ```javascript
    class Rectangle {
    constructor(width, height) {
    this.width = width;
    this.height = height;
    }
    }

const rect = new Rectangle(10, 20);
console.log(rect.width); // 输出 10

7. **事件绑定**
事件绑定中的this是指向触发事件的dom元素。

```javascript
const button = document.getElementById('myButton');

button.addEventListener('click', function() {
  console.log(this === button);
});
// 在按钮点击时输出 true

如何改变this指向

改变 this 指向是在 JavaScript 中常见的需求,特别是当你想要在不同的上下文中调用函数时。以下是几种常见的方法来改变 this 指向:

  1. 使用 call 方法:
    call 方法允许你显式地指定函数内部的 this 值,并且传递参数列表。第一个参数是要绑定的 this 值,后面的参数是函数的参数。

    function greet(message) {
         
      console.log(`${message}, ${this.name}!`);
    }
    
    const person = {
          name: 'Alice' };
    
    greet.call(person, 'Hello'); // 输出 'Hello, Alice!' 这里把this绑定给person对象
    
  2. 使用 apply 方法:
    apply 方法与 call 类似,但它接受一个数组或类数组对象作为参数,其中的元素将作为函数参数传递。

    function greet(message) {
         
      console.log(`${message}, ${this.name}!`);
    }
    
    const person = {
          name: 'Bob' };
    
    greet.apply(person, ['Hi']); // 输出 'Hi, Bob!'
    
  3. 使用 bind 方法:
    bind 方法创建一个新函数,将 this 值永久地绑定,并可以预先设置部分参数。原函数不会受到影响。

    function greet(message) {
         
      console.log(`${message}, ${this.name}!`);
    }
    
    const person = {
          name: 'Charlie' };
    const greetPerson = greet.bind(person);
    
    greetPerson('Hey'); // 输出 'Hey, Charlie!'
    
  4. 使用箭头函数:
    箭头函数不会绑定独立的 this 值,而是捕获其外部函数的 this 值。

    const obj = {
         
      method: function() {
         
        const arrowFunc = () => {
         
          console.log(this === obj);
        };
        arrowFunc();
      }
    };
    
    obj.method(); // 输出 true
    

call和apply区别

  1. bind 方法:
    • bind 方法创建一个新函数,将原函数的 this 值永久绑定到指定的对象,并可以在调用时传递参数。
    • 它不会立即执行原函数,而是返回一个新的函数,需要手动调用新函数以执行原函数。
    • bind 方法不会改变原函数的上下文,而是返回一个新函数。
  2. call 方法:

    • call 方法立即调用函数,并指定函数内部的 this 值,同时可以传递参数列表。
    • 它的第一个参数是要绑定的 this 值,后续的参数会作为函数的参数传递。
  3. apply 方法:

    • apply 方法也立即调用函数,并指定函数内部的 this 值,但参数传递方式不同。
    • 它的第一个参数是要绑定的 this 值,第二个参数是一个数组(或类数组对象),其中的元素会作为函数的参数传递。

实现call、apply、bind

这里实现简化版的,核心思路是:

  1. 将函数设为传入对象的一个属性
  2. 执行该函数
  3. 删除该函数(临时函数调用完成删除,防止内存泄漏,以免context 对象造成污染)
  4. 返回结果或传入的this

    call

js
Function.prototype.myCall = function(context, ...args) {
   
  context = context || window;
  const fn = Symbol();

  context[fn] = this;

  const result = context[fn](...args);
  delete context[fn];

  return result;
}

apply

js
Function.prototype.myApply = function(context, args) {
   
  context = context || window;
  const fn = Symbol();

  context[fn] = this;

  let result;
  if(args) {
   
    result = context[fn](...args);
  } else {
   
    result = context[fn]();
  }

  delete context[fn];
  return result;
}

bind

js
Function.prototype.myBind = function(context, ...outerArgs) {
   
  context = context || window;
  const _this = this;

  return function(...innerArgs) {
   
    context[fn] = _this;
    const result = context[fn](...outerArgs, ...innerArgs);
    delete context[fn];
    return result;
  }
}
目录
相关文章
|
1月前
|
JavaScript 前端开发
js中的bind,call,apply方法的区别以及用法
JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
28 1
|
2月前
|
JavaScript 前端开发
JS高级—call(),apply(),bind()
【10月更文挑战第17天】call()`、`apply()`和`bind()`是 JavaScript 中非常重要的工具,它们为我们提供了灵活控制函数执行和`this`指向的能力。通过合理运用这些方法,可以实现更复杂的编程逻辑和功能,提升代码的质量和可维护性。你在实际开发中可以根据具体需求,选择合适的方法来满足业务需求,并不断探索它们的更多应用场景。
14 1
|
2月前
|
JavaScript 前端开发
js 中call()和apply()
js 中call()和apply()
32 1
|
3月前
|
自然语言处理 JavaScript 前端开发
JS中this的应用场景,再了解下apply、call和bind!
该文章深入探讨了JavaScript中`this`关键字的多种应用场景,并详细解释了`apply`、`call`和`bind`这三个函数方法的使用技巧和差异。
|
1月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
30 1
JavaScript中的原型 保姆级文章一文搞懂
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
108 2
|
1月前
JS+CSS3文章内容背景黑白切换源码
JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
21 0
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
155 4
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
90 4
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的宠物交易平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的宠物交易平台附带文章源码部署视频讲解等
82 4