首頁  >  文章  >  web前端  >  詳解javascript中this屬性

詳解javascript中this屬性

零到壹度
零到壹度原創
2018-04-08 14:28:592678瀏覽

這篇文章主要介紹了javascript中this屬性,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧

this總是回傳一個物件,也就是傳回屬性或方法目前所在的對象。

物件的屬性可以賦給另一個對象,所以屬性所在的目前物件是可變的,也就是this的指向是可變的。

eg:

var A = {
	name : '张三',
	describe : function(){
		return '姓名:' + this.name;
	}
};
var B = {
	name : '李四'
}
B.describe = A.describe;
B.describe();

結果:「姓名:李四」

再看一個例子:

var A = {
	name : '张三',
	describe : function(){
		return '姓名:' + this.name;
	}
};
var name = '李四'
f = A.describe;
f();

結果也是“姓名:李四”,因為這時this指向f執行階段所在的物件-頂層window

this的使用場合

##1、全域環境——無論this是不是在函數內部,只要是在全域環境下運行,this就是指頂層物件window

2、建構函數——指的是實例物件

eg:

var Obj = function(p){
	this.p = p;
}
Obj.prototype.a = function(){
	return this.p;
}
var obj = new Obj('color');
obj.a();
obj.p;

結果是都回傳"color"

上面程式碼定義了一個建構函式Obj,由於this指向實例對象,所以在Obj中定義this.p,相當於定義實例物件有一個p屬性,然後m方法可以回傳這個p屬性。

3、物件的方法

var obj = {
	foo : function(){
		console.log(this);
	}
};
obj.foo();//obj

只有直接在obj物件上呼叫foo方法,this才會指向obj,其他用法時,this都指向程式碼區塊目前所在的物件。

情況一:(obj.foo = obj.foo)()——window

情況二:(false || obj.foo)()——window

#情況三:(1 , obj.foo)()——window

上述程式碼中,obj.foo先運算再執行,即使它的值沒有變化,this也不再指向obj了

4、Node

在Node中,若在全域環境裡,this指向global,模組環境中,this指向module.exports

this使用注意點

1、避免多層this

var o = {
	f1 : function(){
		console.log(this);
		var f2 = function(){
			console.log(this);
		}();
	}
}
o.f1();

執行結果是:

{f1: ƒ}

Window {decodeURIComponent: ƒ, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}

為什麼f2中的this指向的是全域物件呢?因為上面那段程式碼的執行過程其實是

var temp = function(){
	console.log(this);
};
var o = {
	f1 : function(){
		console.log(this);
		var f2 = temp();
	}
}
o.f1();

解決方法一-在第二層改用一個指向外層this的變數

var o = {
	f1 : function(){
		console.log(this);
		var that = this;
		var f2 = function(){
			console.log(that);
		}();
	}
}
o.f1();

使用一個變數固定this的值,然後內層呼叫這個變量,是非常有用且大量應用的方法

解決方法二-使用嚴格模式,在嚴格模式下,如果函數內部的this指向頂層物件就會報錯。

2、避免在陣列處理方法中使用this

var o = {
	v : 'hello',
	p : ['a1','a2'],
	f : function(){
		this.p.forEach(function(item){
			console.log(this.v + ' ' + item);
		});
	}
}
o.f();

結果:

undefined a1

undefined a2

#導致這個結果的原因跟上一段的多層this是一樣的

解決方法一——使用中間變數

var o = {
	v : 'hello',
	p : ['a1','a2'],
	f : function(){
		var that = this;
		this.p.forEach(function(item){
			console.log(that.v + ' ' + item);
		});
	}
}
o.f();

解決方法二——將this當作forEach方法的第二個參數,固定它的運行環境

var o = {
	v : 'hello',
	p : ['a1','a2'],
	f : function(){
		this.p.forEach(function(item){
			console.log(this.v + ' ' + item);
		},this);
	}
}
o.f();

3、避免回呼函數中的this

var o = new Object();
o.f = function(){
	console.log(this === o);
}
o.f();//true
$("#button").on("click",o.f);//false

#綁定this的方法

JavaScript提供了call、apply、 bind三個方法來切換/固定this的指向

function.prototype.call()

函數實例的call方法可以指定函數執行時this所在的作用域,call方法的參數量個對象,如果參數為空、null、undefined,則預設傳入全域對象。如果call的參數不是對象,那麼就會自動包裝成包裝對象。 func.call(thisValue,arg1,arg2,……)

var n = 123;
var obj = {n : 456};
function a(){
	console.log(this.n);
}

a.call();//123
a.call(null);//123
a.call(undefined);//123
a.call(window);//123
a.call(obj);//456

call方法的一個應用是呼叫物件的原生方法

var obj = {};
//原生方法
obj.hasOwnProperty('toString');//false
//覆盖了原生的方法
obj.hasOwnProperty = function(){
	return true;
}
obj.hasOwnProperty('toString');//true
//调回原生的方法
Object.prototype.hasOwnProperty.call(obj,'toString');//false

function.prototype.apply()

apply與call唯一的區別是apply接受一個數組作為函數執行時的參數,func.apply(thisValue,[arg1,arg2,……])

apply的應用之一-找出陣列的最大元素

var a = [10,3,4,2];
Math.max.apply(null,a);

apply的應用程式之二-將陣列的空元素變成undefined(因為陣列的forEach方法會跳過空元素,卻不會跳過undefined)

var a = ['a','','b'];
function print(i){
	console.log(i);
}
a.forEach(print);//a b
Array.apply(null,a).forEach(print);//a undefined b

運行結果跟上面不太一樣,都是a b

apply的應用之三-轉換類似數組的物件

Array.prototype.slice.apply({0:1,length:1});

apply的應用程式之四-綁定回呼函數的物件

var o = new Object();
o.f = function(){
	console.log(this === o);
}
var f = function(){
	o.f.apply(o);//或o.f.call(o);
}
$("#button").on("click",f);

function.prototype.bind()

bind方法用於將函數體內的this綁定到某個對象,然後傳回一個新函數

下面的例子在將方法賦值後會出錯

var d = new Date();
d.getTime();
var print = d.getTime;
print();//Uncaught TypeError: this is not a Date object.

解決方法:

var print = d.getTime.bind(d);

bind比call和apply更進一步的是,除了綁定this以外,還可以綁定原函數的參數

var add = function(x,y){
	return x * this.m + y * this.n;
}
var obj = {
	m:2,
	n:2
}
var newAdd = add.bind(obj,5);//绑定add的第一个参数x
newAdd(5);//第二个参数y

對於那些不支援bind方法的老式瀏覽器,可以自行定義bind方法

if(!('bind' in Function.prototype)){
	Function.prototype.bind = function(){
		var fn = this;
		var context = arguments[0];
		var args = Array.prototype.slice.call(arguments,1);
		return function(){
			return fn.apply(context,args);
		}
	}
}

以上是詳解javascript中this屬性的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn