温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

ES6中javascript实现函数绑定及类的事件绑定功能的案例

发布时间:2021-04-13 11:39:42 来源:亿速云 阅读:240 作者:小新 栏目:web开发

这篇文章主要介绍ES6中javascript实现函数绑定及类的事件绑定功能的案例,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

具体如下:

函数绑定

箭头函数可以绑定this对象,大大减少了显式绑定this对象的写法(call、apply、bind)。但是,箭头函数并不适用于所有场合,所以 ES7 提出了 “ 函数绑定 ” ( function bind )运算符,用来取代call、apply、bind调用。虽然该语法还是 ES7 的一个提案,但是 Babel 转码器已经支持。

函数绑定运算符是并排的两个双冒号( :: ),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即 this 对象),绑定到右边的函数上面。

foo::bar; // 等同于 bar.bind(foo); foo::bar(...arguments); // 等同于 bar.apply(foo, arguments); const hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwn(obj, key) { return obj::hasOwnProperty(key); }

如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上面。

var method = obj::obj.foo; // 等同于 var method = ::obj.foo; let log = ::console.log; // 等同于 var log = console.log.bind(console);

由于双冒号运算符返回的还是原对象,因此可以采用链式写法。

// 例一 import { map, takeWhile, forEach } from "iterlib"; getPlayers() ::map(x => x.character()) ::takeWhile(x => x.strength > 100) ::forEach(x => console.log(x)); // 例二 let { find, html } = jake; document.querySelectorAll("div.myClass") ::find("p") ::html("hahaha");

类中事件绑定

概述

ES6提供了类,给模块化带来了很大的帮助。在类里面绑定事件,一来是为了使得代码结构清晰,二来是为了可以使用类的变量和方法。但是,由于事件的回调函数并不是由类的实例对象触发,所以,事件回调函数里面并不能访问类的this变量。另外,我们也不希望事件回调函数对外暴露,免得调用者直接调用。

简单来说,我们就希望:

1. 事件回调函数要能访问类的this变量
2. 事件回调函数不能直接调用

如何访问类的this

方案一:将类的this保存成一个局部变量

this的指代是动态改变的,但是局部变量的指代却是明确的,并且,函数定义的局部变量在整个函数里面都可以用。所以,我们可以使用let that = this保存类的this变量。

class A{   //绑定事件的方法   bindEvent(){    let that = this;    this.button1.on('click',function(e){       this.addClass('on'); //this指代所点的元素       that.doSomething(); //that指向类的this    })   }   doSomething(){    //事件处理函数   }   //解绑事件   unBindEvent(){    this.button1.off();   } }

这种方法只在使用jquery时有用,因为jquery解绑事件不需要提供回调函数,直接off就可以了。但是原生js需要提供回调函数也有它的道理,因为同一个元素的同一种事件可以绑定多个回调函数,所以你需要指出释放哪一个。

方案二:使用bind()改变this的指向

有类A,在A中要添加mousemove事件,根据需求写出下面代码:

class A{   //添加事件   addEvent(){     document.addEventListener( 'mousemove', onMouseMove, false );   }   //添加事件   removeEvent(){     document.removeEventListener( 'mousemove', onMouseMove , false );   } } //事件回调函数中 function onMouseMove(event){   console.log(this);  //#document }

但是,这样获取不到类的this。onMouseMove的this将会指向document。因为事件是添加到document上的,所以自然是由document触发事件并调用onMouseMove进行处理,所以onMouseMove中的this指向document。

比较正确的做法是:使用bind()函数改变onMouseMove中this的指向,同时将事件回调函数移到类外面:

class A{   //添加事件   addEvent(){     document.addEventListener( 'mousemove', onMouseMove.bind(this), false );   }   //添加事件   removeEvent(){     document.removeEventListener( 'mousemove', onMouseMove.bind(this) , false );   } } //事件回调函数中 function onMouseMove(event){   console.log(this); }

但是这样仍然存在问题,事件移除不掉了!因为this.bind()每次调用都会返回一个新的函数,所以:

document.addEventListener( 'mousemove', onMouseMove.bind(this), false );

document.removeEventListener( 'mousemove', onMouseMove.bind(this), false );

两者的第二个参数并不相同。

正确的做法是: 将bind()的结果保存到一个变量中:

class A{   constructor(){     this._onMouseMove = onMouseMove.bind(this);  //看这里   }   //添加事件   addEvent(){     document.addEventListener( 'mousemove', this._onMouseMove , false );   }   //添加事件   removeEvent(){     document.removeEventListener( 'mousemove', this._onMouseMove , false );   } } //事件回调函数中 function onMouseMove(event){   console.log(this); }

如何定义私有的事件回调函数

在Java中,不想对外暴露的方法可以定义为私有方法,但是ES6并没有提供私有方法,只能通过一些办法模拟。但是,事件回调函数比较特别,因为事件除了定义,还要移除,这会带来额外的麻烦。但还是有办法的:

使用Symbol变量来定义

const _onMouseMove = Symbol("_onMouseMove"); class A{   constructor(){     this[_onMouseMove] = onMouseMove.bind(this);   }   //添加事件   addEvent(){     document.addEventListener( 'mousemove', this[_onMouseMove] , false );   }   //添加事件   removeEvent(){     document.removeEventListener( 'mousemove', this[_onMouseMove] , false );   } } //事件回调函数中 function onMouseMove(event){   console.log(this); }

Symbol("_onMouseMove")会产生一个唯一的值,这个值是在对象创建的时候才生成的,所以,调用者没有办法在写代码时知道这个值的,所以,就无法调用使用这个值命名的方法了,这样就定义了一个私有方法。

以上是“ES6中javascript实现函数绑定及类的事件绑定功能的案例”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI