对象属性

其实我在一年前就想过一个问题,JS有事件机制,那么变量能不能有事件机制呢?[1]

Intro

这个问题就在最近得到了回答[2],然后我试着运用在了最近写的播放器 bp-player [3] 上,效果还可以吧,有时候能达到非常好的使用效果,但是缺点就是不能用太多,可能是我水平太弱没用正确的方式编写吧。

总所周知,JS里除了那几个[4]以外,其它的都是由对象组成,即使是数字,也会自动返回一个Number对象,字符串亦是如此。也因为JS的对象机制,使得这个语言既有趣又坑爹。

1
2
3
4
5
6
7
8
9
Object(999) instanceof Number
//true
Object('helloString') instanceof String
//true

正是因为这样,你才可以用得到诸如'string'.substr(3)(9).toExponential()之类的写法,也才能用到函数的链式写法。

对象的属性

废话不多说了,对象的属性(property)即 一组无序集合中的项目,这个项目一定要有个名字,而且在这一组集合里不会有重名的项目。JS里的对象允许直接添加属性:

1
2
3
4
5
6
7
8
9
10
11
let obj = {};
obj.a = 999;
obj.b = 888;
obj.c = 222;
obj;
//Object {a: 999, b: 888, c: 222}

还有一个比较特别的是,查找对象里一个不存在的属性,则会返回 undefined

1
2
3
4
5
6
7
8
let obj = {};
console.log(obj.a); //undefined
console.log(obj['b']); //undefined

属性行为

对象属性似乎就两种行为,一种是取值(get), 一种是赋值(set)。JS内部通过 gettersetter 来对对象属性进行 取值/赋值 的操作。

对的,我想你可能猜得到了,JS提供了定义属性行为的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let 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);
//20
people.age = -999;
//'这个世界上没有小于0岁的人'
console.log(people.age);
//20

可以使用 Object.defineProperty 方法定义一个对象属性的行为,也可以用 Object.properties 方法定义多个对象属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let obj = {};
Object.definePropertise(obj, {
propertyA: {
get(){
/* do something */
},
set(){
/* do something */
},
},
propertyB: {
get(){
/* do something */
},
set(){
/* do something */
},
}
});

callback

那么,到底可以做什么用?根据我在 bp 上的实践,其实用处挺大的,而且使用得当非常好,比如一个播放器的列表指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class 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

嗯,似乎没有什么好讲了,我也该去睡觉了,唉,还有好多东西要学,好多东西……


  1. 类似于 typechange、valuechange、change之类的名字吗( ↩︎

  2. 《Javascript高级程序设计》 ↩︎

  3. 包括 bp-core.js、bp-frame、bm.js ↩︎

  4. 比如 undefinednulltruefalse之类的…… ↩︎