免费微网站制作教程视频,做58网站怎么赚钱吗,如何做seo,网站建站制作价格原文地址#xff1a;手动实现一个bind函数#xff01; - 知乎
1.bind函数用法
bind()方法用于创建一个新的函数#xff0c;这个新函数接收的第一个参数代表的就是this#xff0c;利用bind()函数我就就可以任意改变函数内部的this指向了。
官网的解释#xff1a; bind()…原文地址手动实现一个bind函数 - 知乎
1.bind函数用法
bind()方法用于创建一个新的函数这个新函数接收的第一个参数代表的就是this利用bind()函数我就就可以任意改变函数内部的this指向了。
官网的解释
bind() 方法创建一个新的函数在 bind() 被调用时这个新函数的 this 被指定为 bind() 的第一个参数而其余参数将作为新函数的参数供调用时使用。 官网解释得也比较通透明了我们这儿为了让大家更加深刻理解bind的用法利用代码来演示一下。
示例代码
scriptlet obj {name: 小猪课堂,age: 20}// 声明一个函数function fn(a, b, c) {console.log(函数内部this指向:, this);console.log(参数列表:, a, b, c);}// 使用bind创建一个新函数let newFn fn.bind(obj, 10, 20, 30);// 调用新函数newFn();// 调用旧函数fn(10, 20, 30);
/script
输出结果 上段代码中我们声明了一个函数fn并且在函数内部打印了this以及参数然后我们利用bind()创建了一个新的函数且第一个参数传入了obj意味着新函数内部的this指向了obj。分别执行两个函数两个函数内部的this指向一个指向了全局一个指向了window。
2.bind函数的特点
如果我们想要手动实现一个bind函数那么非常有必要了解bind函数的特点所以知己知彼方能百战不殆。
从上一节中的代码我们大致总结出了bind函数的以下几个特点
2.1 返回一个新函数
bind函数实际上是对原函数的一个拷贝原函数认可以按照原逻辑处理。
示例代码
scriptlet obj {name: 小猪课堂,age: 20}// 声明一个函数function fn(a, b, c) {console.log(函数内部this指向:, this);console.log(参数列表:, a, b, c);}// 使用bind创建一个新函数let newFn fn.bind(obj, 10, 20, 30);console.log(typeof newFn); // function
/script
2.2 新函数仍可继续传参
bind函数创建的新函数是可以接收参数的之前的列子中我们是在创建的时候就将参数传递了进去实际上可以不必传。
示例代码
scriptlet obj {name: 小猪课堂,age: 20}// 声明一个函数function fn(a, b, c) {console.log(函数内部this指向:, this);console.log(参数列表:, a, b, c);}let newFn fn.bind(obj, 10);newFn(20, 30);
/script
输出结果 上面的输出结果和我们直接在创建的时候传递所有参数得出的结果一致而且上段代码中我们的参数是分开传递的也就是说使用bind创建新函数后调用新函数时函数接收的参数是调用传入的参数创建时传入的参数。
2.3 新函数作为构造函数
如果我们将使用bind创建的新函数当作构造函数来执行那么this的指向将和bind创建时绑定的无关它会指向一个新的引用。
示例代码
scriptlet obj {name: 小猪课堂,age: 20}function fn(name) {this.name name;console.log(函数内部this指向:, this);}let newFn fn.bind(obj);let obj2 new newFn(构造函数);
/script
输出结果 上段代码中我们使用bind新创建了一个函数newFn而且将这个函数的this指向了obj但是我们后续使用的时候使用了new关键词来创建这个时候函数内部的this指向不在指向obj了而是指向了fn。
那么既然this指向了fn那么我们在fn原型上添加属性或方法后obj2是能访问到的。
3.实现bind函数
既然我们知道了bind的几个特点那么我们遵循它的即可特点就可以来实现它了。首先它是返回一个新函数我们可以先把架子搭起来代码如下
Function.prototype.myBind function () {// 返回新函数return function () {// 代码先省略}
}
上段代码只是一个基本的架子我们在里面填充代码就好了。接下来我们需要将函数的this指向为传进来的第一个参数并且使用bind创建的新函数可以继续接收参数代码如下
scriptlet obj {name: 小猪课堂,age: 20}// 手写bind函数Function.prototype.myBind function (context) {const _this this; // 当前函数let args Array.from(arguments).slice(1); // 将参数列表转化为数组,出去第一个参数外// 返回新函数return function () {// context 是传进来的this_this.apply(context, args.concat(Array.from(arguments))); // 利用apply将this指向context参数进行拼接}}// 声明一个函数function fn(a, b, c) {console.log(函数内部this指向:, this);console.log(参数列表:, a, b, c);}let newFn fn.myBind(obj, 10, 20);newFn(30);
/script
上段代码中需要注意的有两点第一点是利用apply函数将函数的this指向了传经来的context第二点是将参数新传进来的参数与args拼接因为我们调用newFn时可能传进来新参数所以需要将新老参数拼接上。
输出结果 上面的输出结果是和直接使用bind函数输出的结果是一样的。上面的代码还不够完善如果我们将创建的新函数以构造函数的方式执行的话this的执行和原生的bind不太一致。
代码如下
scriptlet obj {name: 小猪课堂,age: 20}// 手写bind函数Function.prototype.myBind function (context) {const _this this; // 当前函数let args Array.from(arguments).slice(1); // 将参数列表转化为数组,除去第一个参数外// 返回新函数return function () {// context 是传进来的this_this.apply(context, args.concat(Array.from(arguments))); // 利用apply将this指向context参数进行拼接}}// 声明一个函数function fn(a, b, c) {console.log(函数内部this指向:, this);console.log(参数列表:, a, b, c);}let newFn fn.myBind(obj, 10, 20); // 调用封装的bindlet newFn1 fn.bind(obj, 10, 20); // 调用原生的bindnew newFn(myBind构造函数);new newFn1(bind构造函数);
/script
输出结果 上面的输出结果不一致说明使用原生bind创建的新函数如果使用构造函数的方式执行那么函数内部的this执行会作为一个新的引用指向fn。
修改代码如下
scriptlet obj {name: 小猪课堂,age: 20}// 手写bind函数Function.prototype.myBind function (context) {const _this this; // 当前函数let args Array.from(arguments).slice(1); // 将参数列表转化为数组,除去第一个参数外// 返回新函数let fn function () {// 如果被new调用this应该是fn的实例return _this.apply(this instanceof fn ? this : (context || window), args.concat(Array.from(arguments)))}// 维护fn的原型let temp function () { }temp.prototype _this.prototype;fn.prototype new temp(); // new的过程继承temp原型return fn};// 声明一个函数function fn(a, b, c) {console.log(函数内部this指向:, this);console.log(参数列表:, a, b, c);}let newFn fn.myBind(obj, 10, 20);let newFn1 fn.bind(obj, 10, 20)new newFn(myBind构造函数);new newFn1(bind构造函数);
/script
输出结果 上段代码的输出结果是不是就和实际的bind函数输出结果一样了啊想要理解上段代码大家有必要去学习以下JS中new一个对象发生了什么主要是下面几步
创建一个新对象将构造函数的this赋值给新对象执行构造函数代码给这个新的对象添加属性返回新的对象
具体的new实现过程还需要大家自己去理解。
总结
想要实现bind函数就必须要理解其中的原理无非就是改变this指向的问题。其中唯一的难点就是如何实现构造函数执行的方式也就是要明白js中new一个对象的时候发生了什么