首先咱們要知道this指向哪裏,或者說最終指向哪裏?數組
咱們須要記住一句話,this永遠指向最後調用他的那個對象bash
第一種是運用 call 以下:app
function f(){
console.log(this)
}
var obj = {
f
};
var fn = obj.f;
obj.f(); //obj
fn(); //window
// fn.call(context,1,2,3,4,5,6); call 是直接讓函數執行了
//第一個參數實用來改變函數執行時內部this指向的
// 第二個參數即以後,都是傳給fn函數的實參;
fn.call(obj,677,443,6565);//
fn.call([],2344);
fn.call(1)
Object.prototype.toString.call('') //'[object string]'
var a = new f;
console.log(a.toString());
({}).toString();
Object.prototype.toString.call('')// ({}).tostring === Object.prototype.toString
// 上述 call 執行時,把tostring方法中的this改爲了 字符串 因此 返回的就是 字符串的數據類型
// call 這個方法 在什麼地方存放? Function.prototype
// 本身封裝一個 call
Function.prototype.myCall = function(context,...arg){
// context 就是咱們讓指向的那個值,arg 是要傳給對應函數的實參
// this 就是我們的 f2
// this(...arg) //能實現 讓f2執行,而且把arg中的參數傳給 f2
// 怎麼把f2中的 this 改爲 context ???
// context.eee() eee 這個函數中的this 就是context;
// context.eee = this; // context.eee 跟咱們的 f2 是同一個函數;
// context.eee(...arg);
// delete context.eee // 爲了避免再原有的對象中添加屬性
//var n = Math.random();
var n = Symbol();
context[n] = this;
context[n](...arg);
delete context[n];
}
function f2(a,b){
console.log(this);
console.log(a+b);
}
var obj = {
q:123,
w:234,
e:345
}
f2.myCall(obj,3,3);
call方法能夠用來代替另外一個對象調用一個方法,
複製代碼
第二種是運用apply改變this的指向dom
var obj = {
q:123,w:234
}
var f = function(a,b,c,d){
console.log(this);
console.log(a,b,c,d)
}
f.call(obj,1,2,3,4);
f.apply(obj,[1,2,3,4]);
Math.max(2,3,4,6,8,1,7,9,2,2,7)//
var ary = [2,6,4,7,5,3,8,3,6];
Math.max(...ary);
Math.max.apply(Math,ary);
```
apply和call的目的是同樣的,都是爲了改變當中 this的指向問題 重點區別在於第二個參數
第二個參數是一個數組或者類數組
雖說給咱們的第二個參數是一個集合,可是函數執行的時候,參數仍是跟以前同樣散亂的傳過去的,而不是直接整個所有傳過去。
複製代碼
第三種方法運用bind實現函數
var obj = {a:123}; var f = function(a,b,c){ console.log(this); console.log(a,b,c) } var fn = f.bind(obj,6,5,6) console.log(fn);this
var f2 = (a)=>{
console.log(this)
return a;
}
f2(); // window
f2.call(obj); //window
// Function.prototype.myBind = function(context,...arg){
// // this 是f2
// var _this = this; // _this 這個變量存儲的就是f2函數
// return function (){
// // console.log(this)
// // _this()
// //_this.call(context,...arg)
// _this.apply(context,arg)
// }
// }
Function.prototype.myBind = function(context,...arg){
return (...ary)=>{
this.call(context,...arg,...ary)
}
}
var fn2 = f.myBind(obj,1,2,3,4); //window
// fn2 執行的時候,f2 執行 而且 f2中的 this 改爲了 obj
fn2()
var fun = function(){
console.log(arguments);
console.log(this)
}
var fun2 = fun.bind(obj,666,777);
fun2(333,555)
bind 的用法跟第一種 call是同樣的 跟一種不一樣的是
不讓函數當即執行,而是返回了一個新函數
返回的新函數執行的時候,this指向換掉了;
新函數執行傳遞的參數會補在經過 bind綁定的參數後邊
咱們能夠把 bind 綁定的參數理解成新函數的默認參數
返回值是個新函數,新函數執行的時候讓老函數執行了,
把老函數中的this指向就會給改變。複製代碼