本人在一次面试中,当面试官小姐姐让我重写一下bind函数的时候,一下子蒙圈了,所以特来研究一下。
在手写bind函数之前,我们先来回顾一下三剑客
1.call,apply和bind
现在我们写一个例子看一下
打印
特殊的,假如this那块写了一个1,那么打印出来的就不是1,而是被包装成一个对象
2.手写bind实现
首先看一下下面的代码
猜测一下这个this指向的是谁,这也是一道面试题。指向的是func函数,其实很简单,谁调用它它就指向谁,so不要和原型链搞混了,两码事!
下来我们开始实现
<!DOCTYPE <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
</style>
<script>
Function.prototype.customeBind = function(thisArg,...list){
let self = this; // 目标函数
console.log('customeBind----this----------')
console.log(this); //指向func
console.log('customeBind----this----------')
return function(...arg2){
self.apply(thisArg,[...list,...arg2])
}
}
function func(...arg){
console.log('答案是我,我是func');
console.log(this);//this已经改变,指向{a:1}
console.log(arg);//{1,2,3,4,5,6,7,8}
console.log('答案是我,我是func');
}
// let newFunc = func.bind(1,2,3);
// newFunc(5, 6, 7, 8);
let newFunc2 = func.customeBind({a:1},1,2,3,4);
newFunc2(5,6,7,8);
</Script>
</head>
<body class="Site">
<div class="parent">
</div>
</body>
</html>
下来我们看一下原生的bind
3. 使用构造函数new
我们现在使用构造函数
<!DOCTYPE <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
</style>
<script>
Function.prototype.customeBind = function(thisArg,...list){
let self = this; // 目标函数
return function(...arg2){
self.apply(thisArg,[...list,...arg2])
}
}
function func(...arg){
console.log('答案是我,我是func');
console.log(this);//this已经改变,指向{a:1}
console.log(arg);//{1,2,3,4,5,6,7,8}
console.log('答案是我,我是func');
}
func.prototype.miaov = function(){
console.log(this);
}
let newFunc = func.bind({ a: 1 }, 1, 2, 3);
let newFunc2 = func.customeBind({ a: 1 }, 1, 2, 3, 4);
console.log('原生------------------');
let f1 = new newFunc(5, 6, 7, 8);
console.log(f1);
console.log('自定义-----------------');
let f2 = new newFunc2(5, 6, 7, 8);
console.log(f2);
</Script>
</head>
<body class="Site">
<div class="parent">
</div>
</body>
</html>
继续我们寻找一下miaov这个函数
自定义的找不到啦
这是因为
自己实现的bind函数,如果把返回的新函数当成了构造函数,此时会遇到问题,就是找不到目标函数原型上的方法
我们画图来说明一下吧
上面的图画的对不对,我们就来看以下代码打印一下就知道
<script>
function func(...arg){
console.log('答案是我,我是func');
console.log(this);//this已经改变,指向{a:1}
console.log(arg);//{1,2,3,4,5,6,7,8}
console.log('答案是我,我是func');
}
func.prototype.miaov = function(){
console.log(this);
}
let newFunc = func.bind({ a: 1 }, 1, 2, 3);
let f1 = new newFunc(5, 6, 7, 8);
console.log(f1.miaov);
console.log('看看f1----------------------');
console.log(f1);
</Script>
然后我们进行改正这个情况
<!DOCTYPE <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
</style>
<script>
Function.prototype.customeBind = function(thisArg,...list){
let self = this; // 目标函数
// 自己实现的bind函数,如果把返回的新函数当成了构造函数,此时会遇到问题,
// 就是找不到目标函数原型上的方法
// 解决:让新函数继承目标函数的原型
let Bound = function(...arg2){
self.apply(thisArg,[...list,...arg2])
}
// 以某个对象作为原型创建一个新的对象出来
Bound.prototype = Object.create(self.prototype);
Bound.prototype.custructor = self;
return Bound;
}
function func(...arg){
console.log('答案是我,我是func');
console.log(this);//this已经改变,指向{a:1}
console.log(arg);//{1,2,3,4,5,6,7,8}
console.log('答案是我,我是func');
}
func.prototype.miaov = function(){
console.log(this);
}
let newFunc = func.bind({ a: 1 }, 1, 2, 3);
let newFunc2 = func.customeBind({ a: 1 }, 1, 2, 3, 4);
console.log('原生------------------');
let f1 = new newFunc(5, 6, 7, 8);
console.log(f1.miaov);
console.log('自定义-----------------');
let f2 = new newFunc2(5, 6, 7, 8);
console.log(f2.miaov);
console.log('看看f2');
console.log(f2);
</Script>
</head>
<body class="Site">
<div class="parent">
</div>
</body>
</html>
哦,千呐,这么一个小小的面试题,其实涉及的知识点并不少,脑壳疼。