call与apply与bind异同
- 作用:均为改变this指向
- call/bind传参为多个参数,apply传参为一个参数数组
- bind的时候function函数不执行,需手动执行,call/apply的时候函数自动执行
例子
function Person(name, age) {
this.name = name;
this.age = age;
}
Person('doudou', 28); //执行时,Person内this指向window,执行完后,window.name 就等于doudou
var stu1 = new Person('feifei',29); //执行时,Person内this指向stu1,执行完后,stu1.name 等于feifei
var stu2 = {};
Person.call(stu2, 'fangfang', 27); //改变this指向,Person内this指向stu2,执行完后,stu2.name 等于fangfang
Person.apply(stu2, ['liaoliao', 27]);//改变this指向,Person内this指向stu2,执行完后,stu2.name 等于liaoliao
Person.bind(stu2, ['xiaoxiao', 26])();改变this指向,Person内this指向stu2,执行完后,stu2.name 等于xiaoxiao
实战
call和apply可以用来借用别人的函数来完成自己的功能
//别人写好的函数
function Person(name, age) {
this.name = name;
this.age = age;
}
//借过来用
function Student(name, age, grade, score) {
Person.call(this, name, age);
this.grade = grade;
this.score = score;
}
var stu = new Student('doudou', 28, 2, 99)
call与apply与bind的源码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>手写apply/bind/call</title>
</head>
<body>
<script>
Function.prototype.myApply = function (obj, arr) {
let context = obj || window;
// 此处this指向调用者,Person,谁调用,指向谁,给obj增加Person函数,Person函数里面的this,指向obj
context.func = this;
// 执行函数即可
// 利用扩展运算符,将一个数组转为用逗号分隔的参数序列
context.func(...arr);
// 删除函数
delete context.func;
}
// 利用扩展运算符,函数剩余参数转为一个数组
Function.prototype.myCall = function (obj, ...arr) {
let context = obj || window;
context.func = this;
// 利用扩展运算符,将一个数组转为用逗号分隔的参数序列
context.func(...arr);
delete context.func;
}
Function.prototype.myBind = function (obj, arr) {
let context = obj || window;
let self = this;
// 将apply执行作为函数内返回,要执行这个函数才执行
return function() {
// 此中的this为函数的执行环境
return self.apply(context, arr);
}
}
function Person(name, age) {
this.name = name;
this.age = age;
}
let stu1 = {}, stu2 = {}, stu3 = {};
Person.myApply(stu1, ['liaoliao', 1]);
Person.myCall(stu2, 'feifei', 2);
Person.myBind(stu3, ['xiongxiong', 3])();
console.log(stu1);
console.log(stu2);
console.log(stu3);
</script>
</body>
</html>