摘要:對象方法中的當以對象里的方法的方式調用函數時,它們的是調用該函數的對象。注意,在何處或者如何定義調用函數完全不會影響到的行為。在這次執行期間,函數中的將指向。
原文鏈接
與其他語言相比,函數的this關鍵字在JavaScript中的行為略有不同。并且它在嚴格模式和非嚴格模式之間也有一些區別。
在絕大多數情況下,函數的調用方式決定了this的值。this不能在執行期間被賦值,在每次函數被調用時this的值也可能會不同。ES5引入了bind方法來設置函數的this值,而不用考慮函數如何被調用的。
先來做幾道面試題: 第一道:var name = "caibaojian.com"; var person = { name: "kang", pro: { name: "Michael", getName: function() { return this.name; } } }; console.log(person.pro.getName()); // Michael var pepole = person.pro.getName; console.log(pepole()); // caibaojian.com第二道:
var name = "caibaojian.com"; var person = { name: "kang", pro: { name: "Michael", getName: function() { console.log(this); return this.name; } } }; console.log(person.pro.getName()); // Object { name: "...", getName: () }, Michael var pepole = person.pro.getName; console.log(pepole()); // Window, caibaojian.com第三道:
"use strict"; var name = "caibaojian.com"; var person = { name: "kang", pro: { name: "Michael", getName: function() { console.log(this); return this.name; } } }; console.log(person.pro.getName()); // Object { name: "...", getName: () }, Michael var pepole = person.pro.getName; console.log(pepole()); // undefined第四道:
var name = "caibaojian.com", person = { name : "kang", getName : function(){ return function(){ return this.name; }; } }; console.log(person.getName()()); // caibaojian.com下面一起看看關于this的用法: 一、全局上下文
在全局運行上下文中(在任何函數體外部),this指代全局對象,無論是否在嚴格模式下。在瀏覽器中,全局對象為window對象。
console.log(this.document === document); // true console.log(this === window); // true this.a = 37; console.log(window.a); // 37二、函數上下文
在函數內部,this的值取決于函數是如何調用的。
1、直接調用在非嚴格模式下,this的值不會在函數執行時被設置,此時的this的值會默認設置為全局對象。
function foo(){ return this; } foo() === window; // true
在嚴格模式下,this將保持他進入執行環境時的值,所以下面的this將會默認為undefined
function foo(){ "use strict"; // 嚴格模式 return this; } foo() === undefined; // true
在嚴格模式下,如果this未被執行的上下文環境定義,那么它將會默認為undefined。
2、對象方法中的this當以對象里的方法的方式調用函數時,它們的this是調用該函數的對象。
下面的例子中,當obj.f()被調用時,函數內的this將綁定到obj對象。
var obj = { prop: 37, foo: function() { return this.prop; } }; console.log(obj.foo()); // 37
注意,在何處或者如何定義調用函數完全不會影響到this的行為。
在上一個例子中,我們在定義obj的時候為其成員foo定義了一個匿名函數。但是,我們也可以首先定義函數然后再將其附屬到obj.foo。這樣做this的取值也和上面一致:
var obj = { prop: 37 }; function independent() { return this.prop; } obj.foo = independent; console.log(obj.foo()); // 37
這說明this的值只與函數foo作為obj的成員被調用有關系。
類似的,this的綁定只受最靠近的成員引用的影響。
在下面的這個例子中,我們把一個方法g當作對象obj.b的函數調用。在這次執行期間,函數中的this將指向obj.b。事實上,這與對象本身的成員沒有多大關系,最靠近的引用才是最重要的。
var obj = { prop: 37 }; function independent() { return this.prop; } obj.b = { g: independent, prop: 42 }; console.log(obj.b.g()); // 423、原型鏈中的this
相同的概念在定義在原型鏈中的方法也是一致的。如果該方法存在于一個對象的原型鏈上,那么this指向的是調用這個方法的對象,表現得好像是這個方法就存在于這個對象上一樣。
var obj = { f : function(){ return this.a + this.b; } }; var p = Object.create(obj); p.a = 1; p.b = 4; console.log(p.f()); // 5
在這個例子中,對象p沒有屬于它自己的f屬性,它的f屬性繼承自它的原型。但是這對于最終在obj中找到f屬性的查找過程來說沒有關系;查找過程首先從p.f的引用開始,所以函數中的this指向p。也就是說,因為f是作為p的方法調用的,所以它的this指向了p。這是JavaScript的原型繼承中的一個有趣的特性。
4、getter與setter中的this相同的概念也適用時的函數作為一個getter或者setter調用。作為getter或setter函數都會綁定this到從設置屬性或得到屬性的那個對象。
function modulus(){ return Math.sqrt(this.re * this.re + this.im * this.im); } var obj = { re: 1, im: -1, get phase(){ return Math.atan2(this.im, this.re); } }; Object.defineProperty(obj, "modulus", { get: modulus, enumerable: true, configurable: true }); console.log(obj.phase, obj.modulus); // -0.785 1.4145、構造函數中的this
當一個函數被作為一個構造函數來使用(使用new關鍵字),它的this與即將被創建的新對象綁定。
注意:當構造器返回的默認值是一個this引用的對象時,可以手動設置返回其他的對象,如果返回值不是一個對象,返回this。
function Fn(){ this.a = 37; } var obj = new Fn(); console.log(obj.a); // 37 function Foo(){ this.a = 37; return { a: 38 }; } obj = new Foo(); console.log(obj.a); // 386、call和apply
當一個函數的函數體中使用了this關鍵字時,通過所有函數都從Function對象的原型中繼承的call()方法和apply()方法調用時,它的值可以綁定到一個指定的對象上。
function add(c, d){ return console.log(this.a + this.b + c + d); } var obj = { a: 1, b: 3 }; add.call(obj, 5, 7); // 1 + 3 + 5 + 7 = 16 add.apply(obj, [10, 20]); // 1 + 3 + 10 + 20 = 34
使用call和apply函數的時候要注意,如果傳遞的this值不是一個對象,JavaScript將會嘗試使用內部 ToObject操作將其轉換為對象。因此,如果傳遞的值是一個原始值比如7或foo,那么就會使用相關構造函數將它轉換為對象,所以原始值7通過new Number(7)被轉換為對象,而字符串foo使用new String("foo")轉化為對象,例如:
function bar() { console.log(Object.prototype.toString.call(this)); } bar.call(7); // [object Number]7、bind()方法
ECMAScript 5引入了Function.prototype.bind。調用fn.bind(someObject)會創建一個與fn具有相同函數體和作用域的函數,但是在這個新函數中,this將永久地被綁定到了bind的第一個參數,無論這個函數是如何被調用的。
function fn(){ return this.a; } var g = fn.bind({ a: "azerty" }); console.log(g()); // "azerty" var obj = { a: 37, foo: fn, go: g }; console.log(obj.foo(), obj.go()); // 37, "azerty"8、DOM事件處理函數中的this
當函數被用作事件處理函數時,它的this指向觸發事件的元素(一些瀏覽器在動態添加監聽器時不遵守這個約定,除非使用addEventListener)。
// 獲取文檔中的所有元素的列表 var elements = document.getElementsByTagName("*"); for(var i = 0; i < elements.length; i++){ // 當元素被點擊時,就會變成藍色 elements[i].addEventListener("click", function (e) { e.stopPropagation(); console.log(this); console.log(e.currentTarget); console.log(e.target); // 上面3個值是一樣的 this.style.backgroundColor = "#A5D9F3"; }); }9、內聯事件處理函數中的this
當代碼被內聯處理函數調用時,它的this指向監聽器所在的DOM元素:
上面的alert會顯示button。注意只有外層代碼中的this是這樣設置的:
在這種情況下,沒有設置內部函數的this,所以它指向global/window對象(即非嚴格模式下調用的函數未設置this時指向的默認對象)。
(完)文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81964.html
摘要:前端面試題及答案總結掘金技術征文金三銀四,金九銀十,用來形容求職最好的幾個月。因為的存在,至少在被標準化的那一刻起,就支持異步編程了。然而異步編程真正發展壯大,的流行功不可沒。 showImg(https://segmentfault.com/img/bVVQOH?w=640&h=319); 1、2017前端面試題及答案總結 |掘金技術征文 金三銀四,金九銀十,用來形容求職最好的幾個月...
摘要:前集回顧我們在開開心心做幾道機試題中吐了槽,也順勢展開了機試題之旅,本章我們暫時壓抑自己的吐槽之心,繼續就題目前行。其實和都是構造函數,可以直接調用的。請嘗試完成一個解析模塊本題考查對的理解,各部分都是什么意思。 前集回顧 我們在開開心心做幾道JavaScript機試題 - 01中吐了槽,也順勢展開了機試題之旅,本章我們暫時壓抑自己的吐槽之心,繼續就題目前行。仍然希望對各位正確認識Ja...
摘要:碰到這種面試官,你只有是個題霸,再加上眼緣夠才能順利入圍。只要按照我題目的思路,甚至打出來測試用例看看,就能實現這個題目了。答案根據的,對答案做出修正。另我的答案絕不敢稱最佳,隨時歡迎優化修正。但了解總歸是好的。 我們在長期的面試過程中,經歷了種種苦不堪言,不訴苦感覺不過癮(我盡量控制),然后主要聊聊常見JavaScript面試題的解法,以及面試注意事項 憶苦 面試第一苦,面試官的土 ...
閱讀 3947·2021-10-19 13:23
閱讀 2326·2021-09-09 11:37
閱讀 2507·2019-08-29 15:20
閱讀 3407·2019-08-29 11:08
閱讀 1661·2019-08-26 18:27
閱讀 1764·2019-08-23 12:20
閱讀 3028·2019-08-23 11:54
閱讀 2544·2019-08-22 15:19