1. call ,apply 和 bind 应用场景
1.1. call ,apply
-
call 和 apply 方法都是将函数的 this 指向 call 与 apply 函数的第一个参数。
-
call()方法接受的语法和作用与apply()方法类似,只有一个区别就是call()接受的是一个参数列表,而apply()方法接受的是一个包含多个参数的数组。
-
二者都是函数对象Function的方法,且第一个参数都是要绑定对象的上下文
/*定义一个人类*/
function Person(name,age)
{
this.name=name;
this.age=age;
}
/*定义一个学生类*/
functionStudent(name,age,grade)
{
Person.apply(this,arguments); //Person.call(this,name,age);
this.grade=grade;
}
//创建一个学生类
var student=new Student("zhangsan",21,"一年级");
//测试
alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);
//大家可以看到测试结果name:zhangsan age:21 grade:一年级
//学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢,这个就是apply的神奇之处.
1.2. bind
- bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()第一个参数的值,当然这是绑定哦,不是像call、apply一样直接执行,apply要执行的话还得自己调用。
- bind()函数会创建一个新的绑定函数,这个绑定函数包装了原函数的对象。调用绑定函数通常会执行包装函数。
this.x = 9; //this指向全局的window对象
var module = {
x: 81,
getX: function(){return this.x;}
};
console.log(module.getX()); //81
var retrieveX = module.getX;
console.log(retrieveX()); //9,因为函数是在全局作用域中调用的
// 创建一个新函数,把this绑定到module对象
// 不要将全局变量 x 与 module 的属性 x 混淆
var boundGetX = retrieveX.bind(module);
console.log(boundGetX()); //81
2. call,apply 与 bind 代码实现
- call
// call和apply实现方式类似,只是传参的区别
// 基本思想是把fn.call(obj,args)中的fn赋值为obj的属性,然后调用obj.fn即可实现fn中this指向的改变
Function.prototype.myCall = function(context = window){ //myCall函数的参数,没有传参默认是指向window
context.fn = this //为对象添加方法(this指向调用myCall的函数)
let args = [...arguments].slice(1) // 剩余的参数
let res = context.fn(...args) // 调用该方法,该方法this指向context
delete context.fn //删除添加的方法
return res
}
- apply
Function.prototype.myApply = function(context = window){ //myCall函数的参数,没有传参默认是指向window
context.fn = this //为对象添加方法(this指向调用myCall的函数)
let res
if(arguments[1]){ //判断是否有第二个参数
res = context.fn(...arguments[1])// 调用该方法,该方法this指向context
}else{
res = context.fn()// 调用该方法,该方法this指向context
}
delete context.fn //删除添加的方法
return res
}
- bind
Function.prototype.myBind = function(context = window){
context.fn = this // 调用bind的函数
let args = [...arguments].slice(1) // myBind的参数
let bind = function(){
let args1 = [...arguments].slice() // bind的参数
return context.fn(args.concat(args1))
}
return bind
}