博客
关于我
简单模拟实现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 WebDriver如何打印整个页面源(html)
查看>>
Python WebSocket自动化测试:构建高效接口测试框架
查看>>
Python Web开发
查看>>
Redis 配置文件杂项。
查看>>
Python web自动化测试 —— 文件上传
查看>>
Python web自动化测试 —— 文件上传!
查看>>
Python Web自动化测试开发环境搭建(附安装包与虚拟机环境)
查看>>
python win32api键盘_Python win32api.keybd_event模拟键盘输入
查看>>
python Windows显示当前鼠标坐标
查看>>
python Workbook 表格宽度
查看>>
python | ggplot,一个超强的 Python 库!
查看>>
python | unoconv,一个超厉害的 Python 库!
查看>>
python | webassets,一个超强的 Python 库!
查看>>
python | werkzeug,一个不可思议的 Python 库!
查看>>
python | xlsxwriter,一个实用的 Python 库!
查看>>
python | xlwings,一个非常实用的 Excel 相关的 Python 库!
查看>>
python读取含中文的json
查看>>
python | 提升代码迭代速度的Python重载方法
查看>>
python | 深入理解Python并发编程中的GIL限制与解决方案
查看>>
Python | 爬虫实战——亚马逊搜索页监控(附详细源码)
查看>>