摘要:本文主要主要分文两个部分,第一个部分介绍javascript对象的两种属性,及数据属性和访问器属性。第二个部分详细讲解如何利用访问器属性实现简单的双向数据绑定。
一、javascript对象属性
1.1什么是javascript对象
ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数“。我们可以简单把javascript理解为一组无序的名值对集合,这组名值对中的值可以包括简单数据类型的值(字符串、布尔值等)也可以是应用数据类型的值(对象或函数)。
创建对象也主要有两种方法:第一种方法通过Object()构造函数:
var person = new Object();
person.name = 'jocs';
person.sayName = function(){
console.log(this.name);
};
第二种方法是通过对象字面量语法来申明对象:
var person = {
name: 'jocs',
sayName: function(){
console.log(this.name);
}
};
1.2 Javascript对象的属性
ECMAScript中定义对象有两种属性:数据属性和访问器属性。
1.2.1 数据属性
数据属性包含了数据值的位置,在这个位置可以读取和写入数据值,数据属性拥有四个描述其行为的特性:
1、[[Configurable]]表示能否通过delete删除属性,能否修改属性的特性,或者能够把属性修改为访问器属性。取值可以为true和false。默认值为true。
2、[[Enumerable]]表示能够通过for-in循环来返回属性。默认值为true。
3、[[Writable]]表示能够修改属性的值,默认值为ture。
4、[[Value]]包含这个属性的数据值。默认值为undefined。
要修改属性默认的特性可以通过Object.defineProperty()方法。这个方法接受三个参数,属性所在的对象,属性的名字和一个描述符对象。例如:
<span style="font-size:14px;">var person = {};
Object.defineProperty(person, 'name', {
writable: false,
value: 'Jocs'
});
alert(person.name); // 'Jocs'
person.name = 'ransixi';
alert(person.name); //'Jocs'</span>
特别注意的是,在调用Object.defineProperty()方法的时候,如果不指定,configurable,writable,enumerable的话,特性的默认值都是false。
1.2.2 访问器属性
访问器属性不包括数据值,但是它包括一对函数,分别为:getter和setter函数。在读取访问器属性的时候会调用getter函数,在写入访问器属性的时候会调用setter函数。
访问器属性也拥有四个特性:
1.[[Configurable]]表示能够通过delete删除访问器属性,能够修改属性的特性,或者把属性转为数据属性。
2.[[Enumerable]]表示能够通过for-in循环来返回属性。
3.[[Get]] 在读取访问器属性时调用的函数。默认值为undefined。
4.[[Set]] 在写入访问器属性调用的函数。默认值为undefined。
访问器属性不能够直接在对象上定义,只能够通过Object.defineProperty()方法来定义。
<span style="font-size:14px;">var person = {
_name : 'jocs'
};
Object.defineProperty(person, 'name', {
get: function(){
return this._name;
},
set: function(newValue){
this._name = newValue;
},
configurable: true
});
console.log(person.name); // 'jocs'
person.name = 'ransixi';
console.log(person.name); // 'ransixi'</span>
二、通过访问器属性实现双向数据绑定
//<input type = 'text' id = 'text1'/>
var user ={},input = document.getElementById('text1');
Object.defineProperty(user,'name',{
<span style="white-space:pre"> </span>get: function(){
<span style="white-space:pre"> </span> return input.value;
<span style="white-space:pre"> </span>},
<span style="white-space:pre"> </span>set: function( newValue ){
<span style="white-space:pre"> </span> input.value = newValue;
<span style="white-space:pre"> </span>},
<span style="white-space:pre"> </span>configurable: true
});
<span style="white-space:pre"> </span>input.onchange = function(){
<span style="white-space:pre"> </span> user['name'] = user['name'];
};
通过上面的javascript代码,我们实现了一个input输入框中的值和user中的访问器属性‘name’之间的双向数据绑定。我们在input元素上注册了一个onchange事件,当input输入框中的值发生变化并失去焦点时,会调用事件监听器上的处理函数。处理函数中就一行代码:user['name'] = user['name'];这一行代码其实做了两件事,第一件事是读取user中的访问器属性“name”,也就相应的调用了getter函数。第二件事是把读取的getter函数的返回值(这里是input.value)赋值给了user["name"]。也就相应的调用了setter函数。因此当输入框中数据发生变化时,user访问器属性getter函数返回值也发生了变化。换句话说就是当访问访问器属性的时候所得值也发生了变化。这也就完成了从输入框当user.name的数据绑定。
当我们通过user的访问器属性的setter方法传入newValue时候,input.value的值也被赋值成了newValue.也就就完成了从user的访问器属性到输入框input的数据绑定。从而实现了双向数据绑定。
但是当有两个输入框中的值想同时绑定user.name的时候怎么办呢?
var user = {},
input1 = document.getElementById('text1'),
input2 = document.getElementById('text2');
function twoWayBind(obj, property, ele1, ele2){
Object.defineProperty(obj, property, {
get: function(){
return ele1.value;
},
set: function(newValue){
ele2.value = newValue;
},
configurable: true
});
ele1.onchange = function(){
obj[property] = obj[property];
};
ele2.onchange = function(){
ele1.value = this.value;
};
}
twoWayBind(user, 'name', input1, input2);
实现原理和一个输入框差不多,都是通过对象的访问器属性上面的getter和setter方法。唯一区别是,我们在input2输入框上面注册了一个事件,当input2输入框中内容发生变化时,input1中输入框的内容被赋值为input2输入框中的内容。当user.name调用setter函数的时候,input2输入框的内容被赋值成为了newValue。这样就完成了两个输入框和user的访问器属性‘name’之间的双向数据绑定。