博客
关于我
简单模拟实现javascript中的call、apply、bind方法
阅读量:432 次
发布时间:2019-03-06

本文共 2618 字,大约阅读时间需要 8 分钟。

模拟实现JavaScript中的call、apply、bind方法

隐式丢失问题

在JavaScript中,函数的this指针在某些情况下会经历隐式丢失。这种现象通常发生在以下场景:

场景1:引用传递

var a = 'window';function foo() {    console.log(this.a);}var obj = {    a: 'obj',    foo: foo};obj.foo(); // 输出: 'obj',此时`this`指向`obj`var lose = obj.foo; // lose() 的`this`指向`window`lose(); // 输出: 'window'

场景2:作为回调函数传入

var a = 'window';function foo() {    console.log(this.a);}var obj = {    a: 'obj',    foo: foo};function lose(callback) {    callback();}lose(obj.foo); // 输出: 'window',此时`this`指向`window`

总结

无论函数如何被传递,只要它没有被显式绑定,最后一次调用都会应用默认绑定规则。因此,在处理隐式丢失问题时,我们需要找到一种方法,确保函数在被调用时this指向正确的上下文。

硬绑定

硬绑定是一种解决隐式丢失问题的方法。它允许我们在函数被定义时,明确指定其this指针的上下文。这种绑定方式一旦建立后,无论函数如何被调用,其this指针都不会改变。

示例

var a = 'window';function foo() {    console.log(this.a);}var obj = {    a: 'obj',    foo: foo};lose(obj.foo); // 输出: 'window',此时`this`指向`window`// 通过硬绑定解决问题var fixTheProblem = obj.foo.bind(obj);lose(fixTheProblem); // 输出: 'obj',此时`this`指向`obj`

模拟实现原理分析

模拟实现call方法

Function.prototype._call = function($this, ...parms) {    var funcCaller = this;    $this['caller'] = funcCaller;    $this['caller'](...parms);    delete $this['caller'];};

模拟实现apply方法

Function.prototype._apply = function($this, parmsArr) {    var funcCaller = this;    $this['caller'] = funcCaller;    $this['caller'](...parmsArr);    delete $this['caller'];};

模拟实现bind方法

Function.prototype._bind = function($this, ...parms) {    var bindCaller = this;    return function() {        return bindCaller._apply($this, parms);    };};

总体实现

function interface4CallAndApply(caller, $this, parmsOrParmArr) {    $this['caller'] = caller;    $this['caller'](...parmsOrParmArr);    delete $this['caller'];}Function.prototype._call = function($this, ...parms) {    var funcCaller = this;    interface4CallAndApply(funcCaller, $this, parms);};Function.prototype._apply = function($this, parmsArr) {    var funcCaller = this;    interface4CallAndApply(funcCaller, $this, parmsArr);};Function.prototype._bind = function($this, ...parms) {    var bindCaller = this;    return function() {        return bindCaller._apply($this, parms);    };};

测试

var foo = {    name: 'foo',    sayHello: function(a, b) {        console.log(`hello, get the parms: ${a} and ${b}`);    }};var bar = {    name: 'bar'};foo.sayHello._call(bar, 'Fitz', 'smart');foo.sayHello._apply(bar, ['Fitz', 'smart']);var baz = foo.sayHello._bind(bar, 'Fitz', 'smart');baz();// 测试硬绑定的应用var testHardBind = foo.sayHello._bind(bar, 'hard', 'bind');testHardBind._call(Object.create(null));// 输出: 'hello, get the parms: hard and bind'

本文通过模拟实现JavaScript中的call、apply和bind方法,探讨了隐式丢失问题以及硬绑定解决方案的原理。通过实际代码示例,验证了不同方法在不同场景下的表现。

转载地址:http://mcnuz.baihongyu.com/

你可能感兴趣的文章
Python基础——Thread创建管理多线程
查看>>
Python基础——SQLite数据库基本操作
查看>>
Python基础——MySQL数据库基本操作
查看>>
Python基础_列表 list
查看>>
python系列【仅供参考】:python异步库调用gevent和asyncio对比
查看>>
python基础3
查看>>
Python基础08 面向对象的基本概念
查看>>
Python基础-函数篇
查看>>
python基础---->常用模块
查看>>
Python基础(2):控制结构
查看>>
Python基础 | 关于“循环”那些事
查看>>
python系列【仅供参考】:python之subprocess模块rsync拉取文件
查看>>
python系列【仅供参考】:python 远程rdp
查看>>
python基础
查看>>
Python基本语法与变量类型
查看>>
python基本数据类型(容器)- tuple list dict set
查看>>
python基本工资的调整方案_Python薪资又涨了!这可咋办!
查看>>
Python基准测试和性能分析内存管理和垃圾回收
查看>>
Python基于RESTful风格的接口自动化测试实战
查看>>
python基于flask搭建http服务(四)—— Docker容器化部署
查看>>