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的綁定對象。

function greet(message) {console.log(`${message}, ${this.name}!`);
}const person = { name: 'Bob' };greet.call(person, 'Hello'); // 輸出 'Hello, Bob!'
  1. 箭頭函數:
    箭頭函數不綁定this,它會捕獲外層作用域的this值作為自己的this。
const obj = {method: function() {const arrowFunc = () => {console.log(this === obj);};arrowFunc();}
};obj.method(); // 輸出 true
  1. class中的this:
    類中的this默認指向類的實例對象。
class Rectangle {constructor(width, height) {this.width = width;this.height = height;}
}const rect = new Rectangle(10, 20);
console.log(rect.width); // 輸出 10
  1. 事件綁定
    事件綁定中的this是指向觸發事件的dom元素。
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;}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/40699.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/40699.shtml
英文地址,請注明出處:http://en.pswp.cn/news/40699.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入學習前端開發,掌握HTML、CSS、JavaScript等技術

課程鏈接: 鏈接: https://pan.baidu.com/s/1WECwJ4T8UQfs2FyjUMbxig?pwdi654 提取碼: i654 復制這段內容后打開百度網盤手機App,操作更方便哦 --來自百度網盤超級會員v4的分享 課程介紹: 第1周:HTML5基礎語法與標簽 &#x1f…

web集群學習:搭建 LNMP應用環境

目錄 LNMP的介紹: LNMP組合工作流程: FastCGI介紹: 1、什么是 CGI 2、什么是 FastCGI 配置LNMP 1、部署LNMP環境 2、配置LNMP環境 LNMP的介紹: 隨著 Nginx Web 服務的逐漸流行,又岀現了新的 Web 服務環境組合—…

【Spring Cloud 八】Spring Cloud Gateway網關

gateway網關 系列博客背景一、什么是Spring Cloud Gateway二、為什么要使用Spring Cloud Gateway三、 Spring Cloud Gateway 三大核心概念4.1 Route(路由)4.2 Predicate(斷言)4.3 Filter(過濾) 五、Spring …

如何使用Kali Linux進行密碼破解?

今天我們探討Kali Linux的應用,重點是如何使用它來進行密碼破解。密碼破解是滲透測試中常見的任務,Kali Linux為我們提供了強大的工具來幫助完成這項任務。 1. 密碼破解簡介 密碼破解是一種滲透測試活動,旨在通過不同的方法和工具來破解密碼…

力扣初級算法(數組拆分)

力扣初級算法(數組拆分) 每日一算法: 力扣初級算法(數組拆分) 學習內容: 1.問題描述 給定長度為 2n 的整數數組 nums ,你的任務是將這些數分成 n 對, 例如 (a1, b1), (a2, b2), …, (an, bn) …

機器人CPP編程基礎-03變量類型Variables Types

機器人CPP編程基礎-02變量Variables 全文AI生成。 C #include<iostream>using namespace std;main() {int a10,b35; // 4 bytescout<<"Value of a : "<<a<<" Address of a : "<<&a <<endl;cout<<"Val…

[Openwrt]一步一步搭建MT7981A uboot、atf、openwrt-21.02開發環境操作說明

安裝ubuntu-18.04 軟件安裝包 ubuntu-18.04-desktop-amd64.iso 修改ubuntu管理員密碼 sudo passwd [sudo] password for w1804: Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully 更新ubuntu源 備份源 sudo cp /etc/apt/so…

CentO7.9安裝Docker

文章目錄 CentO7.9安裝Docker刪除舊版本的Docker安裝Docker倉庫安裝Docker安裝最新版本安裝指定版本 Docker安裝個NGINX查看Docker鏡像運行查看Docker進程查看啟動端口停止Docker容器 CentO7.9安裝Docker 刪除舊版本的Docker sudo yum remove docker \docker-client \docker-…

Vue+ElementUI實現選擇指定行導出Excel

這里記錄一下&#xff0c;今天寫項目時 的一個需求&#xff0c;就是通過復選框選中指定行然后導出表格中選中行的Excel表格 然后這里介紹一個工具箱(模板)&#xff1a;vue-element-admin 將它拉取后&#xff0c;運行就可以看到如下界面&#xff1a; 這里面的很多功能都已經實現…

【NAS群暉drive異地訪問】使用cpolar遠程訪問內網Synology Drive「內網穿透」

文章目錄 前言1.群暉Synology Drive套件的安裝1.1 安裝Synology Drive套件1.2 設置Synology Drive套件1.3 局域網內電腦測試和使用 2.使用cpolar遠程訪問內網Synology Drive2.1 Cpolar云端設置2.2 Cpolar本地設置2.3 測試和使用 3. 結語 前言 群暉作為專業的數據存儲中心&…

jupyter切換conda虛擬環境

環境安裝 conda install nb_conda 進入你想使用的虛擬環境&#xff1a; conda activate your_env_name 在你想使用的conda虛擬環境中&#xff1a; conda install -y jupyter 在虛擬環境中安裝jupyter&#xff1a; conda install -y jupyter 重啟jupyter 此時我們已經把該安裝…

也許你正處于《孤注一擲》中的“團隊”,要留心了

看完這部電影&#xff0c;心情久久不能平靜&#xff0c;想了很多&#xff0c;倒不是擔心自己哪天也成為“消失的yaozi”&#xff0c;而是在想&#xff0c;我們每天所賴以生存的工作&#xff0c;跟電影里他們的工作比&#xff0c;差別在哪里呢&#xff1f; 目錄 1. 產品的本質…

Linux系統下的性能分析命令

在 Linux 系統下&#xff0c;有許多用于性能分析和調試的命令和工具&#xff0c;可以幫助您識別系統瓶頸、優化性能以及調查問題。本文將介紹在性能分析過程中&#xff0c;可能使用到的一些命令。 以下是一些常用的性能分析命令和工具匯總&#xff1a; 命令功能簡述top用于實…

2023-08-16力扣每日一題

鏈接&#xff1a; 2682. 找出轉圈游戲輸家 題意&#xff1a; 環形1到n&#xff0c;從1開始&#xff0c;每次移動 第i次*k &#xff0c;當移動到出現過的序號時停下&#xff0c; 求沒移動到的數字 解&#xff1a; 簡單模擬題&#xff0c;我也以為有數學做法&#xff0c;可…

docker安裝部署

目錄 docker安裝部署 1.環境 2.安裝步驟 1.安裝必要工具 2.配置軟件源 3.修改軟件源 4.更新并下載docker 5.設置開機自啟 3.啟動docker 1.配置docker鏡像加速器 2.啟動服務 docker安裝部署 1.環境 centos7 2.安裝步驟 1.安裝必要工具 yum install -y yum-utils dev…

【QT+ffmpeg】QT+ffmpeg 環境搭建

1.qt下載地址 download.qt.io/archive/ 2. win10sdk 下載 https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/ 安裝 debug工具路徑 qtcreater會自動識別 調試器選擇

最長連續序列

題目&#xff1a; 給定一個未排序的整數數組 nums &#xff0c;找出數字連續的最長序列&#xff08;不要求序列元素在原數組中連續&#xff09;的長度。 示例 1&#xff1a; 輸入&#xff1a;nums [100,4,200,1,3,2] 輸出&#xff1a;4 解釋&#xff1a;最長數字連續序列是…

74、75、76——tomcat項目實戰

tomcat項目實戰 tomcat 依賴 java運行環境,必須要有jre , 選擇 jdk1.8 JvmPertest 千萬不能用 kyj易捷支付 項目機器 選擇 一臺機器 ,安裝jdk1.8的機器下載tomcat的包 上傳到機器,解壓tomcattomcat文件 bin文件夾: 啟動文件 堆棧配置文件 catalina.sh JAVA_OPTS="-Xm…

gitlab合并新項目和分支切換

一、新建項目 1、創建空白項目 2、先創建一個群組 3、編寫群組信息 4、創建群組完成以后新建項目 ??????? 二、將代碼推送到gitlab 1、初始化 git init 2、關聯gitlab地址 # 比如:http://192.168.139.128:7070/cloud/obwt_cloud.git git remote add origin <你…

FreeRTOS qemu mps2-an385 bsp 移植制作 :串口打印篇

相關文章 FreeRTOS qemu mps2-an385 bsp 移植制作 &#xff1a;環境搭建篇 FreeRTOS qemu mps2-an385 bsp 移植制作 &#xff1a;系統啟動篇 FreeRTOS qemu mps2-an385 bsp 移植制作 &#xff1a;系統運行篇 開發環境 Win10 64位 VS Code&#xff0c;ssh 遠程連接 ubuntu …