扫码关注微信公众号
回复“面试手册”,获取本站PDF版
回复“简历”,获取高质量简历模板
回复“加群”,加入程序员交流群
回复“电子书”,获取程序员类电子书
先回顾下call,apply,bind的区别和用法:call 和 apply 的主要作用,是改变对象的执行上下文,并且是立即执行的。它们在参数上的写法略有区别;bind 也能改变对象的执行上下文,它与 call 和 apply 不同的是,返回值是一个函数,可以延后调用
call()
var name = 'John'
var obj = {
name: 'Jack'
}
function getName(num1,num2){
console.log(this.name + num1 + num2)
}
console.log(getName(1,2)) // John12
console.log(getName.call(obj,1,2)) // 使用call将this指向obj,输出Jack12
apply()
var name = 'John'
var obj = {
name: 'Jack'
}
function getName(num1,num2){
console.log(this.name + num1 + num2)
}
console.log(getName(1,2)) // John12
console.log(getName.apply(obj,[1,2])) // 使用apply将this指向obj,与call不同的是,参数形式是数组,输出Jack12
bind()
var name = 'John'
var obj = {
name: 'Jack'
}
function getName(num1,num2){
console.log(this.name + num1 + num2)
}
console.log(getName(1,2)) // John12
console.log(getName.bind(obj)(1,2)) // 使用bind将this指向obj,与call和apply不同的是,返回值是一个函数,需要再次用,
//输出Jack12
手写一个call
Function.prototype.selfCall = function(target, ...args) {
if (typeof this !== "function") { // 判断调用对象是不是函数
throw new TypeError("not a function")
}
target = target || window // 绑定对象不存在时,指向window对象
target.fn = this // 函数的this指向隐式绑定到target上,改变构造函数的调用者间接改变 this 指向
let result = target.fn(...args) // 此时调用的是target.fn,this指向target
return result
};
var name = 'John'
var obj = {
name: 'Jack'
}
function getName(num1,num2){
console.log(this.name + num1 + num2)
}
console.log(getName(1,2)) // John12
console.log(getName.selfCall(obj,1,2)) // Jack12
手写一个apply
Function.prototype.selfApply = function(target) {
if (typeof this !== "function") { // 判断调用对象是不是函数
throw new TypeError("not a function");
}
if (!Array.isArray(arguments[1])) { // 判断第二个传参是不是数组
throw new Error('arg not a array')
}
target = target || window // 绑定对象不存在时,指向window对象
target.fn = this // 函数的this指向隐式绑定到target上,改变构造函数的调用者间接改变 this 指向
let args = arguments[1] // 获取函数的传参
let result = target.fn(...args) // 此时调用的是target.fn,this指向target,因为传参是数组,解构后传入函数执行。
return result
};
var name = 'John'
var obj = {
name: 'Jack'
}
function getName(num1,num2){
console.log(this.name + num1 + num2)
}
console.log(getName(1,2)) // John12
console.log(getName.selfApply(obj,[1,2])) // Jack12
手写一个bind
Function.prototype.selfBind = function(thisArg) {
if (typeof this !== 'function') {
throw TypeError("Bind must be called on a function");
}
const args = Array.prototype.slice.call(arguments, 1),
self = this,
// 构建一个干净的函数,用于保存原函数的原型
nop = function() {},
// 绑定的函数
bound = function() {
// this instanceof nop, 判断是否使用 new 来调用 bound
// 如果是 new 来调用的话,this的指向就是其实例,
// 如果不是 new 调用的话,就改变 this 指向到指定的对象 o
return self.apply(
this instanceof nop ? this : thisArg,
args.concat(Array.prototype.slice.call(arguments))
);
};
// 箭头函数没有 prototype,箭头函数this永远指向它所在的作用域
if (this.prototype) {
nop.prototype = this.prototype;
}
// 修改绑定函数的原型指向
bound.prototype = new nop();
return bound;
}
var name = 'John'
var obj = {
name: 'Jack'
}
function getName(num1,num2){
console.log(this.name + num1 + num2)
}
console.log(getName(1,2)) // John12
console.log(getName.selfBind(obj)(1,2)) // Jack12
本站链接:https://www.mianshi.online,如需勘误或投稿,请联系微信:lurenzhang888
点击面试手册,获取本站面试手册PDF完整版