Javascript函数绑定
来源:互联网 发布:spark sql 数据仓库 编辑:程序博客网 时间:2024/06/10 06:57
Javascript函数绑定
当我们在
setTimeout
函数中使用对象方法或传递对象方法,会出现丢失this
的问题。this突然停止工作,这个场景对新手来说很常见,即使有经验的开发这也会遇到。
失去this
我们已经知道在Javascript中很容易丢失this
,一旦一个方法被传递值和对象分离的地方时,this
丢失。
这里看看在setTimeout
中是如何发生的:
let user = { firstName: "John", sayHi() { alert(`Hello, ${this.firstName}!`); }};setTimeout(user.sayHi, 1000); // Hello, undefined!
我们看到,输出this.firstName
的结果并不是“John”,而是underfined
。
那是因为setTimeout
获得函数user.sayHi
,其和所属对象分离了,最后一行也能被重新成这样:
let f = user.sayHi;setTimeout(f, 1000); // lost user context
浏览器内置方法setTimeout
有点特殊:函数调用时其设置this=window
(Node.JS中this为timer对象),所以this.firstName
即为window.firstName
,结果不存在。很其他我们将看到情况类似,通常this
变为underfined
.
很典型的任务是我们想传递对象方式至其他地方执行(这里是计划执行),如何确保其在正确的上下文中被调用。
方案1:包装器
最简单的方案是使用一个包装函数:
let user = { firstName: "John", sayHi() { alert(`Hello, ${this.firstName}!`); }};setTimeout(function() { user.sayHi(); // Hello, John!}, 1000);
现在可以正常运行,因为其从外部词法环境中获得user
,然后正常调用方法。可以更短实现同样任务:
setTimeout(() => user.sayHi(), 1000); // Hello, John!
看起来不错,但在我们代码结构中有点漏洞。
如果在触发setTimeout
函数之前user
的值变化了(因为有1秒延迟),会怎样?那么,它将调用错误的对象!
let user = { firstName: "John", sayHi() { alert(`Hello, ${this.firstName}!`); }};setTimeout(() => user.sayHi(), 1000);// ...within 1 seconduser = { sayHi() { alert("Another user in setTimeout!"); } };// Another user in setTimeout?!?
下一个解决方案保证这样的事情不会发生。
方案2:绑定
函数提供了一个内置方法bind
,允许我们修改this。基本的语法为:
// more complex syntax will be little laterlet boundFunc = func.bind(context);
调用func.bind(context)
的结果是,指定一个外部对象作为可调用函数的上下文,设置this=context
.
换句话说,调用绑定函数就如func
带了固定的this
。
举例,这里funcUser
传递一个调用给func
,同时指定this=user
:
let user = { firstName: "John"};function func() { alert(this.firstName);}let funcUser = func.bind(user);funcUser(); // John
这里func.bind(user)
如func
的绑定变量,并带有this=user
.
所有其他参数被传递给原来的func
函数,举例:
let user = { firstName: "John"};function func(phrase) { alert(phrase + ', ' + this.firstName);}// bind this to userlet funcUser = func.bind(user);funcUser("Hello"); // Hello, John (argument "Hello" is passed, and this=user)
现在让我们尝试一个对象方法:
let user = { firstName: "John", sayHi() { alert(`Hello, ${this.firstName}!`); }};let sayHi = user.sayHi.bind(user); // (*)sayHi(); // Hello, John!setTimeout(sayHi, 1000); // Hello, John!
星号行我们让给方法user.sayHi
绑定至user
,sayHi是“绑定”函数,可以单独调用或传递给setTimeout——没关系,上下文会是正确的。
这里我们看到参数可以正常传递,仅this
通过bind给固定了。
let user = { firstName: "John", say(phrase) { alert(`${phrase}, ${this.firstName}!`); }};let say = user.say.bind(user);say("Hello"); // Hello, John ("Hello" argument is passed to say)say("Bye"); // Bye, John ("Bye" is passed to say)
便利的方法:bindAll
如果一个对象有很多方法,且都需要绑定,我们可以通过循环进行绑定:
for (let key in user) { if (typeof user[key] == 'function') { user[key] = user[key].bind(user); }}
Javascript库也提供了函数用于便捷批量绑定,obj.func.bindAll(obj).
总结
方法func.bind(context,...args)
返回一个函数func的绑定变量,其固定上下文this为第一个给定参数。
通常我们应用绑定去固定对象方法的上下文this,所以我们能放置在其他地方,如在setTimeout
中。在未来的开发中,我们会遇到更多的绑定场景。
- JavaScript函数绑定
- javascript函数绑定
- javascript中的函数绑定
- JavaScript函数绑定
- es6 javascript 函数绑定
- Javascript函数绑定
- Javascript-bind绑定函数
- JavaScript-bind()与函数绑定
- javascript动态绑定带参数的函数
- 动态绑定javascript函数的共用方法
- javascript使用bind()函数绑定this
- JavaScript之函数绑定与函数柯里化(高级函数)
- JavaScript函数绑定Demo以及函数Currying柯里化
- javascript中动态绑定带参数的函数
- javascript 动态绑定函数的参数传递例子
- JavaScript跨浏览器的添加删除事件绑定函数
- JavaScript跨浏览器的添加删除事件绑定函数
- JavaScript中为事件句柄绑定监听函数
- 运算符重载实现字符串串接
- 决策树算法介绍与代码编写
- 通用无限分类的方法
- JS学习(9)----JS Functions
- HDU5135Little Zu Chongzhi's Triangles(状态压缩DP)
- Javascript函数绑定
- 前端div的弹出,html弹窗思路
- I
- 从单一WAR到多活, 记述一个创业公司的架构演变
- 西部开源运维学习unit9
- SpringMVC文件上传与删除
- C#ListView详解(二)
- 不懂技术的研发团队领导
- PAT 1040有几个PAT