
回复
call 和 apply 的主要作用,是改变对象的执行上下文,并且是立即执行的。它们在参数上的写法略有区别;bind 也能改变对象的执行上下文,它与 call 和 apply 不同的是,返回值是一个函数,并且需要稍后再调用一下,才会执行。
一、call
call 的写法
Function.call(obj,[param1[,param2[,…[,paramN]]]])
var name = 'name'
var obj = {
name: 'objName'
}
function getName(p1, p2) {
console.log(p1, p2,this.name)
}
getName(1, 2) //1 2 "name"
getName.call(obj, 1, 2)//1 2 "objName"
需要注意以下几点:
function func (a,b,c) {}
func.call(obj, 1,2,3)
// func 接收到的参数实际上是 1,2,3
func.call(obj, [1,2,3])
// func 接收到的参数实际上是 [1,2,3],undefined,undefined
function myCall(context) {
//判断一下
if (typeof this !== 'function'){
throw new TypeError('error')
}
//this指向,谁去执行去这个函数
context = context || window
//要执行的函数
context.fn = this
//取出参数
const args = [...arguments].slice(1)
//执行函数
const result = context.fn(...args)
//删除fn
delete context.fn
return result
}
Function.prototype.myCall = myCall
getName.myCall(obj, 1, 2)//1 2 "objName"
二、applay
apply使用与call大体一致,只是接受参数的方法不同。call可以接收多个参数。apply接收的第一个参数是this,第二个参数是 所需参数所组成的数组。
Function.apply(obj[,argArray])
applay模拟实现
function myApply(context) {
if (typeof this !== 'function') {
throw new TypeError('Error');
}
context = context || window;
context.fn = this;
var result;
if (arguments[1]) {
result = context.fn(...arguments[1]);
} else {
result = context.fn();
}
delete context.fn;
return result;
}
三、bind
Function.bind(thisArg[, arg1[, arg2[, ...]]])
bind 方法 与 apply 和 call 比较类似,也能改变函数体内的 this 指向。不同的是,bind 方法的返回值是函数,并且需要稍后调用,才会执行。而 apply 和 call 则是立即调用。
bind模拟实现
function myBind(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
const _this = this
const args = [...arguments].slice(1)
// 返回函数
return function F() {
// 1 判断是否用作构造函数
if (this instanceof F) {
return new _this(...args, ...arguments)
}
// 2 用作普通函数
return _this.apply(context, args.concat(...arguments))
}
}
验证一下:
普通函数
Function.prototype.myBind = myBind
var name = 'name'
var obj = {
name: 'objName'
}
function test(p1, p2){
this.a = p1
this.b = p2
console.log(this.name,p1, p2)
}
var f1 = test.myBind(obj, 1)
f1(2)//objName 1 2
构造函数
var name = 'name'
var obj = {
name: 'objName'
}
function test(p1, p2){
this.a = p1
this.b = p2
console.log(this.name,p1, p2)//undefined 1 2
}
var f1 = test.myBind(obj, 1)
var f= new f1(2)
console.log(f)//test {a: 1, b: 2}
应用场景
1.对象的继承
function superClass () {
this.value = 123;
this.print = function () {
console.log(this.value);
}
}
function subClass () {
superClass.call(this);
this.print();
}
subClass();
//123
2.借用方法
使类数组可以使用Array 原型链上的方法
let domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
3.Math.max||Math.min
let arr = [1,2,3,4,5];
console.log(Math.max.apply(this,arr))//5
console.log(Math.min.call(this,...arr))//1
4.数组合并
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
Array.prototype.push.apply(arr1, arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]
————————————————
版权声明:本文为博主「LYFlied」的原创文章