在百题斩js中的这些“this”指向都值得了解中已经简要概述了call、apply、bind三个方法,这三者作用是相同的,均可以改变this指向,从而让某对象可以调用自身不具备的方法,本节将深入理解这三者的实现原理。
宝坻网站建设公司成都创新互联,宝坻网站设计制作,有大型网站制作公司丰富经验。已为宝坻上千余家提供企业网站建设服务。企业网站搭建\外贸网站建设要多少钱,请找那个售后服务好的宝坻做网站的公司定做!
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。其返回值是使用调用者提供的this值和参数调用该函数的返回值,若该方法没有返回值,则返回undefined。
基本用法:
- function.call(thisArg, arg1, arg2, ...)
小试牛刀
- function method(val1, val2) {
- return this.a + this.b + val1 + val2;
- }
- const obj = {
- a: 1,
- b: 2
- };
- console.log(method.call(obj, 3, 4)); // 10
15.1.2 实现
实现一个call函数,将通过以下几个步骤:
- Function.prototype.myCall = function (context, ...args) {
- // 获取第一个参数(注意第一个参数为null或undefined时,this指向window),构建对象
- context = context ? Object(context) : window;
- // 将对应函数传入该对象中
- context.fn = this;
- // 获取参数并执行相应函数
- let result = context.fn(...args);
- // 消除副作用
- delete context.fn;
- // 返回结果
- return result;
- }
- // ……
- console.log(method.myCall(obj, 3, 4)); // 10
15.2.1 基础
apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。其返回值是指定this值和参数的函数的结果。call() 和 apply()的区别是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组;
基本用法
- func.apply(thisArg, [argsArray])
小试牛刀
- function method(val1, val2) {
- return this.a + this.b + val1 + val2;
- }
- const obj = {
- a: 1,
- b: 2
- };
- console.log(method.apply(obj, [3, 4])); // 10
15.2.2 实现
apply和call的区别主要是参数的不同,所以其实现步骤的call大体类似,如下所示:
- Function.prototype.myApply = function (context, arr) {
- context = context ? Object(context) : window;
- context.fn = this;
- let result = arr ? context.fn(...arr) : context.fun();
- delete context.fn;
- return result;
- }
- // ……
- console.log(method.myApply(obj, [3, 4])); // 10
15.3.1 基础
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。该函数的返回值是一个原函数的拷贝,并拥有指定的this值和初始参数。
基本用法
- function.bind(thisArg[, arg1[, arg2[, ...]]])
小试牛刀
- function method(val1, val2) {
- return this.a + this.b + val1 + val2;
- }
- const obj = {
- a: 1,
- b: 2
- };
- const bindMethod = method.bind(obj, 3, 4);
- console.log(bindMethod()); // 10
15.3.2 实现
实现一个bind函数相对较复杂一些,应该注意以下几点:
- Function.prototype.myBind = function (context, ...args) {
- if (typeof(this) !== 'function') {
- throw new TypeError('The bound object needs to be a function');
- }
- const self = this;
- // 定义一个中装函数
- const fNOP = function() {};
- const fBound = function(...fBoundArgs) {
- // 利用apply改变this指向
- // 接受多个参数+支持柯里化形式传参
- // 当返回值通过new调用时,this指向当前实例 (因为this是当前实例,实例的隐士原型上有fNOP的实例(fnop);fnop instanceof fNOP为true)
- return self.apply(this instanceof fNOP ? this : context, [...args, ...fBoundArgs]);
- }
- // 将调用函数的原型赋值到中转函数的原型上
- if (this.prototype) {
- fNOP.prototype = this.prototype;
- }
- // 通过原型的方式继承调用函数的原型
- fBound.prototype = new fNOP();
- return fBound;
- }
本文转载自微信公众号「执鸢者」,可以通过以下二维码关注。转载本文请联系执鸢者公众号。
分享标题:前端百题斩——快速手撕Call、Apply、Bind
本文地址:http://www.mswzjz.com/qtweb/news18/195968.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联