這篇文章主要介紹了關於Javascript中的this對象,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
對於this的使用,我們最常遇到的主要有,在全域函數中,在物件方法中,call和apply時,在閉包中,箭頭函數中以及class中;
我們知道this物件是在運行時基於函數的執行環境綁定的,在呼叫函數之前,this的值並不確定,因此this會在程式碼執行過程中引用不同的物件。哪個物件實例呼叫this所在的函數,那麼this就代表哪個物件實例。
1. 全域函數
在全域函數中,this等於window;
var name = "Tina";function sayName() { alert(this.name); } person();//Tina
在這裡,由於函數person()是在全域環境中執行的,也是在全域作用域中window物件呼叫的person();故此時的this便指向window物件。而當把這個函數賦給物件o並呼叫o.sayName()時,this引用的是物件o,因此對this.name的求值就變成了對o.name求值。
name = "Tina"
2. 物件方法
#當函數被當作某個物件的方法呼叫時,this等於那個物件;
var name="Tina";var obj={ name="Tony", getName: function() { alert(this.name); } }; obj.getName();//"Tony"
3.call()和apply( )和bind()
我們知道,call(ctx, parm1,parm2,parm3...)和apply(ctx,[parms])的用途都是在在特定的作用域中呼叫函數,實際上等於設定函數體內this物件的值;
function sum(num1, num2) { return num1+num2; }function callSum1(num1, num2) { return sum.apply(this, [num1, num2]); }function callSum2(num1,num2) { return sum.call(this, num1, num2); } alert(callSum1(10, 10)); //20alert(callSum2(10, 10));//20
在上面的範例中,callSum1()和callSum2( )在執行函數sum()時傳入了this作為this值(因為是在全域作用域中呼叫的,所以傳入的就是window物件);事實上,call和apply最強之處是能夠擴充函數賴以運作的作用域;來看下面的例子:
window.color="red";var o={ color: "blue"};function sayColor() { alert(this.color); } sayColor();//"red"sayColor.call(this);//"red"sayColor.call(window);//"red"sayColor.call(o);//"blue"
# bind()方法會建立一個函數的實例,其this值會被綁定到傳給bind()函數的值。例如:
window.color="red";var o={ color: "blue" };function sayColor() { alert(this.color); }var objsayColor = sayColor.bind(o); objsayColor();//"blue"
另一個使用場景是函數綁定,函數綁定要建立一個函數,可以在特定的this環境中以指定參數呼叫另一個函數,該技巧常常和回呼函數與事件處理程序一起使用,以便在將函數作為變數傳遞的同時保留程式碼執行環境。
var handler = { message: "Event handled", handleClick : function(event) { alert(this.message); } };var btn = document.getElementById("my_btn"); btn.addEventListener("click", handler.handleClick, false);
當按下該按鈕時,就呼叫該函數,顯示一個警告框,雖然看似警告框應該顯示Event handled,然而實際上顯示的是undefined。原因在於沒有儲存handler.handleClick()的執行環境,所以this物件最後指向了DOM按鈕而非handler(在IE8中,this指向window)。一種方法,可以使用一個閉包來修正這個問題。
var handler = { message: "Event handled", handleClick : function(event) { alert(this.message); } };var btn = document.getElementById("my_btn"); btn.addEventListener("click", function(event){ handler.handleClick(event); }, false);
這個解決方案在onclick事件處理程序內使用了一個閉包直接呼叫handler.handleClick(),當然,這是特定與本段程式碼的解決方案。我們知道,創建多個閉包可能會讓程式碼變得難以理解和調試。因此,許多JS函式庫實作了一個可以將函數綁定到指定環境的函數,這個函數一般叫bind();ECMAScript 5為所有函數定義了一個原生的bind()方法,它的使用方式如下:
var handler = { message: "Event handled", handleClick : function(event) { alert(this.message+":"+event.type); } };var btn = document.getElementById("my_btn"); btn.addEventListenr("click", handler.handleClick.bind(handler), false);
一個簡單的bind()函數接受一個參數和一個環境,並傳回一個在給定環境中呼叫給定函數的函數,並且將所有參數原封不動地傳遞過去。語法如下:
function bind(fn, context) { return function() { return fn.apply(context, arguments); }; }
這個函數在bind()中建立了一個閉包,閉包使用apply呼叫傳入的函數,並傳遞給applycontext物件個arguments物件數組,這裡的arguments物件是內部函數(匿名函數)的,而非bind()的參數。當呼叫返回的函數時,它會在給定環境中執行被傳入的函數並給出所有參數。
原生的bind()方法和前面自訂的bind()方法類似,都是要傳入作為this值的物件。它們主要用於事件處理程序以及setTimeout()和setInterval()。 bind綁定在react事件處理中也常常和箭頭函數一樣起到綁定this的效果。
4. 閉包
有時候,由於寫閉包的方式不同,在閉包中使用this物件可能會導致一些問題;
var name = "The window";var object = { name: "My Object", getNameFunc: function() { return function() { return this.name; }; } }; alert(object.getNameFunc()());//"The window"
由于getNameFunc()返回一个函数,因此调用object.getNameFunc()()就会立即调用它返回的函数,结果就是返回一个字符串"The window",即全局变量的值,此时匿名函数没有取得其包含作用域(外部作用域)的this对象。原因在于内部函数在搜索两个特殊变量this和arguments时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。这时,只需把把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了。
var name = "The window";var object = { name: "My Object", getNameFunc: function() { var that = this; return function() { return that.name; }; } }; alert(object.getNameFunc()());//"My Object"
//节流function throttle(fn, delay) { var previous = Data.now(); return function() { var ctx = this; var args = arguments; var now = Data.now(); var diff = now-previous-delay; if(diff>=0) { previous = now; setTimeout(function() { fn.apply(ctx, args); }, delay); } }; }
5. 箭头函数
我们知道,箭头函数有几个需要注意的点:
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象;
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误;
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替;
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数;
这里我们只谈论第一点;this对象的指向是可变的,但在箭头函数中,它是固定的;
function foo() { setTimeout(() => { console.log('id: ', this.id); }, 100); }var id=21; foo.call({id: 31});//id: 31
上述代码中,setTimeout是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它真正加入到执行栈后还要等到100毫秒后才会执行,如果是普通函数,此时的this应该指向全局对象window,这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id:31})所以输出的是id: 31;
箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。下面是另一个例子:
function Timer() { this.s1 = 0; this.s2 = 0; setInterval(() => this.s1++, 1000); setInterval(function() { this.s2++; }, 1000); }var timer = new Timer(); setTimeout(() => console.log('s1: ', timer.s1), 3100);//s1: 3setTimeout(() => console.log('s2: ', timer.s2), 3100);//s2: 0
上面代码中,Timer函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的this绑定定义时所在的作用域(Timer函数),后者的this指向运行时所在的作用域(即全局对象)。所以,3100毫秒后,timer.s1被更新了3次,timer.s2一次都没更新。
箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。下面代码将DOM事件的回调函数封装在一个对象里面。
var handler = { id: '123456', init: function() { document.addEventListener('click', event => this.doSomething(event.type), false); }, doSomething: funcition(type) { console.log('Handling ' + type + ' for ' + this.id); } };
上面代码的init方法中,使用了箭头函数,这导致这个箭头函数里面的this,总是指向handler对象。否则,回调函数运行时,this.doSomething这一行会报错,因为此时this指向document对象。this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码的this。正是因为它没有this,所以也就不能用作构造函数。由于箭头函数没有自己的this,所以当然不能用call()、apply()、bind()改变this的指向。
6. class
类的方法内部如果含有this,它默认指向类的实例。
class Logger { /*constructor() { this.printName = this.printName.bind(this); }*/ printName(name = 'Nicolas') { this.print(`Hello ${name}`); } print(text) { console.log(text); } } const logger = new Logger(); const { printName } = logger; printName();
上面代码中,printName方法中的this,默认指向Logger类的实例。但是,如果将这个方法提取出来单独使用,this会指向该方法运行时所在的环境,因为找不到print方法而导致报错。一种简单的解决方法就是在构造函数中绑定this。而另一种方法是使用箭头函数:
class Logger { constructor() { this.printName = (name='Nicolas') => { this.print(`Hello ${name}`); } print(text) { console.log(text); } } const logger = new Logger(); const { printName } = logger; printName();
还有一种方法是使用Proxy,获取方法的时候,自动绑定this。
function selfish (target) { const cache = new WeakMap(); const handler = { get (target, key) { const value = Reflect.get(target, key); if (typeof value !== 'function') { return value; } if (!cache.has(value)) { cache.set(value, value.bind(target)); } return cache.get(value); } }; const proxy = new Proxy(target, handler); return proxy; } const logger = selfish(new Logger());
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
以上是Javascript中的this對象的詳細內容。更多資訊請關注PHP中文網其他相關文章!

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

Atom編輯器mac版下載
最受歡迎的的開源編輯器

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

禪工作室 13.0.1
強大的PHP整合開發環境