this指向
this-運行期綁定,this指向調(diào)用時決定拍顷。
- 全局 this指向window
- 函數(shù)中抚太,若有調(diào)用者,則this指向調(diào)用者昔案;若為獨立調(diào)用尿贫,則this為undefined。在非嚴格模式中踏揣,當this指向undefined時庆亡,它會被自動指向全局對象。
- call/apply/bind 可以改變this指向為第一個參數(shù)
- new this指向新構(gòu)造出來的實例對象
- 箭頭函數(shù)捞稿,沒有自己的this又谋,會捕獲上下文中的this指向拼缝,即最近的非箭頭函數(shù)中的this指向。
- dom事件中彰亥,this指向DOM節(jié)點咧七。
call
function.call(thisArg, arg1, arg2, ...)
thisArg
可選的。在function
函數(shù)運行時使用的this
值任斋。請注意继阻,this
可能不是該方法看到的實際值:如果這個函數(shù)處于非嚴格模式下,則指定為null
或undefined
時會自動替換為指向全局對象废酷,原始值會被包裝瘟檩。
arg1, arg2, ...
指定的參數(shù)列表。
返回
調(diào)用有指定this值和參數(shù)的函數(shù)的結(jié)果锦积。
芒帕!參數(shù)一個個列表式傳入
Function.prototype.call2 = function (context) {
// 如果沒傳this指向,則指向window
var context = context || window;
// 把要調(diào)用的函數(shù)綁定到對象上, Symbol保證唯一性丰介,不覆蓋已有屬性
var fn = Symbol();
context[fn] = this;
// 處理參數(shù)列表
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push(arguments[i]);
}
// 執(zhí)行函數(shù)
var result = context.fn(...args);
// 刪除綁定
delete context.fn
// 返回結(jié)果
return result;
}
Function.prototype.call3 = function(context) {
return this.apply([].shift.apply(arguments), arguments);
}
apply
func.apply(thisArg, [argsArray])
thisArg
必選的背蟆。在func
函數(shù)運行時使用的this
值。請注意哮幢,this
可能不是該方法看到的實際值:如果這個函數(shù)處于[非嚴格模式]下带膀,則指定為null
或undefined
時會自動替換為指向全局對象,原始值會被包裝橙垢。
argsArray
可選的垛叨。一個數(shù)組或者類數(shù)組對象,其中的數(shù)組元素將作為單獨的參數(shù)傳給func
函數(shù)柜某。如果該參數(shù)的值為 [null
]嗽元,則表示不需要傳入任何參數(shù)。從ECMAScript 5 開始可以使用類數(shù)組對象喂击。
返回
調(diào)用有指定this值和參數(shù)的函數(shù)的結(jié)果剂癌。
!參數(shù)以數(shù)組形式傳入
Function.prototype.apply2 = function (context翰绊,args) {
// 如果沒傳this指向佩谷,則指向window
var context = context || window;
// 把要調(diào)用的函數(shù)綁定到對象上, Symbol保證唯一性,不覆蓋已有屬性
var fn = Symbol();
context[fn] = this;
// 執(zhí)行函數(shù)
var result = context.fn(...args);
// 刪除綁定
delete context.fn
// 返回結(jié)果
return result;
}
Function.prototype.apply3 = function(context, args) {
return this.call(context, ...args)
}
bind
Function.prototype.bind2 = function (context) {
var self = this;
// 獲取bind2函數(shù)從第二個參數(shù)到最后一個參數(shù)
var args = Array.prototype.slice.call(arguments, 1);
return function () {
// 這個時候的arguments是指bind返回的函數(shù)傳入的參數(shù)
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(context, args.concat(bindArgs));
}
}
Function.prototype.bind = Function.prototype.bind || function bind(thisArg){
// 非函數(shù)調(diào)用监嗜,直接報錯
if(typeof this !== 'function'){
throw new TypeError(this + ' must be a function');
}
var self = this;
var args = [].slice.call(arguments, 1);
var bound = function(){
// 處理參數(shù)合并
var boundArgs = [].slice.call(arguments);
var finalArgs = args.concat(boundArgs);
// new 當構(gòu)造函數(shù)使用
// 用new.target判斷更準確
if(this instanceof bound){
if(self.prototype){
function Empty(){}
Empty.prototype = self.prototype;
bound.prototype = new Empty();
}
var result = self.apply(this, finalArgs);
// 構(gòu)造函數(shù)返回值為非對象谐檀、函數(shù),返回構(gòu)造出的實例對象
var isObject = typeof result === 'object' && result !== null;
var isFunction = typeof result === 'function';
if(isObject || isFunction){
return result;
}
return this;
}
else{
return self.apply(thisArg, finalArgs);
}
};
return bound;
}