var person = {
value : 1
}
function bar() {
console.log(this.value)
}
// 若是不對this進行綁定執行bar() 會返回undefined,this指向window
bar.call(person) // 1複製代碼
試想一下當調用call的時候也就相似於數組
var person = { value: 1,
bar: function() {
console.log(this.value)
}
}
person.bar() // 1複製代碼
這樣就把 this 指向到了 person上,可是這樣給 person 對象加了一個屬性,不太合適,不過沒關係,執行完刪除這個屬性就能夠實現了。
bash
也就是說步驟實際上是這樣的app
Function.prototype.call = function(context){
context = context ? Object(context) : window;//不傳遞context默認爲window
context.fn = this;//this也就是調用call的函數
let args = [...arguments].slice(1);
let r = context.fn(...args);
delete context.fn;
return r;
}複製代碼
apply
的方法和 call
方法的實現相似,只不過是若是有參數,以數組形式進行傳。
函數
Function.prototype.apply= function(context,args){
context = context ? Object(context) : window;//不傳遞context默認爲window
context.fn = this;
if(!args){
return context.fn();
}
let r = context.fn(...args);
delete context.fn;
return r;
}複製代碼
用法:ui
let obj = {
name:'gjf'
}
function fn(){
console.log(this.name)
}
let bindFn = fn.bind(obj); //返因一個綁定後的方法
findFn() //用綁定後的方法,讓原方法執行複製代碼
實現:this
Function.prototype.bind = function(context){
let that = this;
return function(){
return that.apply(context);
}
}複製代碼
這樣實現了最簡單的改變this指向的bind,可是這樣還遠遠不夠,由於bind還能夠綁定參數;spa
方法傳參能夠分兩批傳,一批能夠先在bind方法裏面先綁定好,另外一批在調用的時候傳參,例如如下示例;prototype
用法:code
let obj = {
name:'gjf'
}
function fn(name,age){
console.log(this.name+'養了一隻'+name+age+'歲了')
}
let bindFn = fn.bind(obj,'貓'); //返因一個綁定後的方法
findFn(8) //用綁定後的方法,讓原方法執行複製代碼
實現:對象
Function.prototype.bind = function(context){
let that = this;
let bindArgs = Array.prototype.slice.call(argument,1)//['貓']
return function(){
let args = Array.prototype.slice.call(argument);
return that.apply(context,bindArgs.concat(args));
}
}複製代碼
調用bind返回的函數除了能夠直接調用,還能夠把函數當成一個類來調用;原函數上綁定了屬性,new出來的實例上可否訪問。
用法:
fn.prototype.flag = '哺乳類'; //原函數上綁定了屬性
let findFn = fn.bind(obj,'貓');
let instance = new findFn(8);//若是綁定的函數被new了,當前函數的this就是當前的實例
console.log(instance.flag) //undefined複製代碼
實現:
Function.prototype.bind = function(context){
let that = this;
let bindArgs = Array.prototype.slice.call(argument,1)//['貓']
function Fn(){} //Object.create的原理
function fBound(){
let args = Array.prototype.slice.call(argument);
return that.apply(this instanceof fBound ? this:context,bindArgs.concat(args));
}
Fn.prototype = this.prototype;
fBound.prototype = new Fn();
return fBound;
}複製代碼
這裏,咱們js裏的三種改變this指向的方法就實現啦。。。。。