首先咱们要知道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指向就会给改变。复制代码