其实我在一年前就想过一个问题,JS有事件机制,那么变量能不能有事件机制呢?[1]
Intro
这个问题就在最近得到了回答[2],然后我试着运用在了最近写的播放器 bp-player
[3] 上,效果还可以吧,有时候能达到非常好的使用效果,但是缺点就是不能用太多,可能是我水平太弱没用正确的方式编写吧。
总所周知,JS里除了那几个[4]以外,其它的都是由对象组成,即使是数字,也会自动返回一个Number对象,字符串亦是如此。也因为JS的对象机制,使得这个语言既有趣又坑爹。
123456789Object(999) instanceof Number//trueObject('helloString') instanceof String//true
正是因为这样,你才可以用得到诸如'string'.substr(3)
、(9).toExponential()
之类的写法,也才能用到函数的链式写法。
对象的属性
废话不多说了,对象的属性(property)即 一组无序集合中的项目,这个项目一定要有个名字,而且在这一组集合里不会有重名的项目。JS里的对象允许直接添加属性:
1234567891011let obj = {};obj.a = 999;obj.b = 888;obj.c = 222;obj;//Object {a: 999, b: 888, c: 222}
还有一个比较特别的是,查找对象里一个不存在的属性,则会返回 undefined
12345678let obj = {};console.log(obj.a); //undefinedconsole.log(obj['b']); //undefined
属性行为
对象属性似乎就两种行为,一种是取值(get), 一种是赋值(set)。JS内部通过 getter
和 setter
来对对象属性进行 取值/赋值 的操作。
对的,我想你可能猜得到了,JS提供了定义属性行为的方式。
123456789101112131415161718192021222324252627282930let people = { name: 'vec', _age: 19,};Object.defineProperty(people, 'age', { get(){ return this._age; }, set(value){ if ( value < 0 ){ alert('这个世界上没有小于0岁的人'); }else{ this._age = value; } }});people.age = 20;console.log(people.age);//20people.age = -999;//'这个世界上没有小于0岁的人'console.log(people.age);//20
可以使用 Object.defineProperty
方法定义一个对象属性的行为,也可以用 Object.properties
方法定义多个对象属性。
1234567891011121314151617181920212223let obj = {};Object.definePropertise(obj, { propertyA: { get(){ /* do something */ }, set(){ /* do something */ }, }, propertyB: { get(){ /* do something */ }, set(){ /* do something */ }, }});
callback
那么,到底可以做什么用?根据我在 bp
上的实践,其实用处挺大的,而且使用得当非常好,比如一个播放器的列表指针
123456789101112131415161718192021222324252627282930313233343536373839404142class List{ getCurrent(){ return this.list[this.cursor]; } reloadSong(){ this.audio.src = this.getCurrent(); this.audio.load(); this.audio.play(); } constructor(list){ this.audio = new Audio; this.list = list; this._cursor = 0; Object.defineProperty(this, 'cursor', { get(){ return this._cursor; }, set(value){ if ( isNaN(value) ){ alert('请使用有效的数字'); } else if ( value >= this.list.length ){ alert('你这个数值设定的太大了'); } else if ( value < 0 ){ alert('小于0也是不行不能不可以的'); }else{ this._cursor = parseInt(value); this.reloadSong(); } } }); this.reloadSong(); }}
只要正确修改了 cursor
属性,就会执行一次reloadSong
方法,对于使用者来说,只需要换个 cursor 就可以切换曲目了,个人觉得挺简洁的
但是,东西虽好,可不要多玩。。。我之前在bm.js上的实践就是这样,写的很乱,有点后怕了orz
嗯,似乎没有什么好讲了,我也该去睡觉了,唉,还有好多东西要学,好多东西……