call()
call() 方法可以是对象重用其他对象上的方法,此方法是JS预定义的,可以用来调用所有者对象作为参数的方法
用法示例:
const fully = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const p = {
firstName:"Jhon",
lastName: "Park",
}
fully.fullName.call(p); // 返回 "Jhon Park"
接收参数:
const fully = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
const p = {
firstName:"Jhon",
lastName: "Park"
}
fully.fullName.call(p, "La", "USA"); // 返回 "Jhon Park,La,USA"
手写实现:
/**
* 当第一个参数为null/undefined,this指向全局对象window,
* 若值为原始值则指向该原始值的自动包装对象,如 String、Number、Boolean
* 为了避免函数名与上下文(ctx)的属性发生冲突,使用Symbol类型作为唯一值
* 将函数作为传入的上下文(ctx)属性执行
* 函数执行完成后删除该属性
* 返回执行结果
* */
const person = {
firstName: 'Jhon',
lastName: 'Park'
}
const fully = {
fullName: function(){
return this.firstName + ' ' + this.lastName
}
}
Function.prototype.newCall = function(context,...args){
let cxt = context || window;
//新建一个唯一的Symbol变量避免重复
let fn = Symbol()
// cxt[fn]定义当前被调用的方法,绑定this以便用对象形式调用
cxt[fn] = this;
args = args ? args : []
//以对象调用形式调用fn,此时this指向cxt 也就是传入的需要绑定的this指向
const res = args.length > 0 ? cxt[fn](...args) : cxt[fn]();
//删除该方法,不然会对传入对象造成污染
delete cxt[fn];
return res;
}
const result1 = fully.fullName.newCall(person)
console.log('Call:', result1);
apply()
与call()方法非常相似,apply() 方法可以是对象重用其他对象上的方法,此方法是JS预定义的,可以用来调用所有者对象作为参数的方法
用法示例:
const fully = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const p = {
firstName:"Jhon",
lastName: "Park",
}
fully.fullName.apply(p); // 返回 "Jhon Park"
接收参数:
const fully = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
const p = {
firstName:"Jhon",
lastName: "Park"
}
fully.fullName.apply(p, ["La", "USA"]); // 返回 "Jhon Park,La,USA"
手写实现:
const fully = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const person2 = {
firstName: 'Anna',
lastName: 'Wang'
}
Function.prototype.newApply = function(context,args = []){
let cxt = context || window;
let func = Symbol()
cxt[func] = this;
const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
delete cxt[func];
return res;
}
const result2 = fully.fullName.newApply(person2)
console.log('Apply:', result2); // Apply: Anna Wang
call() 与 apply():
call 与 apply 的相同点:
方法的含义是一样的,即方法功能是一样的;
第一个参数的作用是一样的;
call 与 apply 的不同点:两者传入的列表形式不一样
call可以传入多个参数;
apply只能传入两个参数,所以其第二个参数往往是作为数组形式传入
如果要使用数组而不是参数列表,则 apply() 方法非常方便。
bind()
bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()第一个参数的值,bind() 除了 this 外,还可传入多个参数,创建的新函数可能传入多个参数,新函数可能被当做构造函数调用,函数可能有返回值。
用法示例:
const fully = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const p = {
firstName:"Jhon",
lastName: "Park",
}
fully.fullName.bind(p)(); // 返回 "Jhon Park"
接收参数:
const fully = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
const p = {
firstName:"Jhon",
lastName: "Park"
}
fully.fullName.bind(p)("La", "USA"); // 返回 "Jhon Park,La,USA"
手写实现:
const fully = {
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
const person3 = {
firstName: 'Kay',
lastName: 'Sun'
}
Function.prototype.newBind = function (context, ...args) {
//新建一个变量赋值为this,表示当前函数
const fn = this
//判断有没有传参进来,若为空则赋值[]
args = args ? args : []
//返回一个newFn函数,在里面调用fn
return function newFn(...newArgs) {
if (this instanceof newFn) {
return new fn(...args, ...newArgs)
}
return fn.apply(context, [...args,...newArgs])
}
}
const result3 = fully.fullName.newBind(person3)()
console.log('Bind:', result3); // 返回 Bind: Kay Sun