5.8 属性的访问

生成的对象可以通过属性来访问。对于对象的引用可以使用点运算符(.)或中括号运算符([])来访问其属性。需要注意的是,在点运算符之后书写的属性名会被认为是标识符,而中括号运算符内的则是被转为字符串值的式子。请看下面的例子:

var hzh1 = { x:3, y:4 };
console.log("输出hzh对象的x属性:");
console.log("hzh1.x = " + hzh1.x);     // 属性x
console.log("hzh1[x] = " + hzh1['x']); // 属性x
var hzh2 = 'x';
console.log("hzh1[hzh2] = " + hzh1[hzh2]); // 属性x(而非属性key)
[Running] node "e:\HMV\JavaScript\JavaScript.js"
输出hzh对象的x属性:
hzh1.x = 3
hzh1[x] = 3
hzh1[hzh2] = 3

[Done] exited with code=0 in 0.181 seconds

不过,对于对象字面量的属性名来说,下面这样的标识符或字符字面量形式的表示,都没问题。请注意不要与上面的规则混淆。

var hzh1 = 'x';
var hzh2 = { hzh1:3 }; // 属性hzh1(而非属性x)
var hzh2 = { 'x':3 };  // 属性x

这里需要多提一句,属性访问的运算对象并不是变量,而是对象的引用。这一点,可以从以下直接 对对象字面量进行运算的示例中得到确认:

console.log("确认属性访问的运算对象是对象的引用:");
console.log({x:3, y:4}.x);    // 属性x
console.log({x:3, y:4}['x']); // 属性x
[Running] node "e:\HMV\JavaScript\JavaScript.js"
确认属性访问的运算对象是对象的引用:
3
3

[Done] exited with code=0 in 0.183 seconds

现实中几乎不会对对象字面量进行运算。不过当这种运算对象不是一个变量时,倒是常常会以方法链之类的形式出现。

5.8.1 属性值的更新

在赋值表达式的左侧书写属性访问表达式能够实现对属性值的改写。如果指定的是不存在的属性名,则会新增该属性。下面将不再使用右侧或左侧的说法,而改用属性读取,以及属性写入这样的术语。

可以使用 delete 运算表达式来删除属性。这里需要注意的是,很难区分不存在的属性属性值为undefined 值的属性

5.8.2 点运算符与中括号运算符在使用上的区别

有时选择用于访问对象属性的这两个运算符只凭偏好。点运算符的表述较为简洁,所以通常都会选用点运算符。不过,中括号运算符的通用性更高。

能使用点运算符的情况一定也可以使用中括号运算符,反之未必成立。但也无需因此全都使用中括号运算符。通常认使用表述简洁的点运算符,只有在不得不使用中括号运算符的情况下,才使用中括号运算符。

只能使用中括号运算符的情况分为以下几种。

  • 使用了不能作为标识符的属性名的情况。
  • 将变量的值作为属性名使用的情况。
  • 将表达式的求值结果作为属性名使用的情况。

包含数值或横杠(-)的字符串不能作为标识符使用。无法作为标识符使用的字符串,不能用于点运算符的属性名,且对于保留字,也有这样的限制。不过,原本就不应该将保留字作为属性名使用,所以这里不再赘述。

像下面这样,将含有横杠的属性名用于点运算符会引起错误

// 含有横杠的属性名
var hzh = { 'huang-zihan':5 };
console.log(hzh.huang-zihan); // 将解释为hzh.huang减去zihan,从而造成错误
[Running] node "e:\HMV\JavaScript\JavaScript.js"
e:\HMV\JavaScript\JavaScript.js:3
console.log(hzh.huang-zihan); // 将解释为hzh.huang减去zihan,从而造成错误
                      ^

ReferenceError: zihan is not defined
    at Object.<anonymous> (e:\HMV\JavaScript\JavaScript.js:3:23)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

[Done] exited with code=1 in 0.413 seconds

无法作为标识符被使用的字符串,仍可以在中括号运算符中使用。请看下面的例子,其中以字符串值指定了一个属性名。

// 含有横杠的属性名
var hzh = { 'huang-zihan':5 };
console.log(hzh['huang-zihan']); // 使用[]运算以字符串值指定了一个属性名。可以正常执行
[Running] node "e:\HMV\JavaScript\JavaScript.js"
5

[Done] exited with code=0 in 0.773 seconds

数值也是如此。数组对象的属性名都是数值。由于点运算符无法使用数值,因此只能使用中括号运算符。而且很多程序设计语言都是通过中括号运算符来访问数组的元素,所以可读性也随之提高。

下面的例子仍使用了之前的代码,用于展示将被变量的值作为属性名使用的情况。

var hzh1 = { x:3, y:4 };
console.log("输出hzh对象的x属性:");
console.log("hzh1.x = " + hzh1.x);     // 属性x
console.log("hzh1[x] = " + hzh1['x']); // 属性x
var hzh2 = 'x';
console.log("hzh1[hzh2] = " + hzh1[hzh2]); // 属性x(而非属性key)
[Running] node "e:\HMV\JavaScript\JavaScript.js"
输出hzh对象的x属性:
hzh1.x = 3
hzh1[x] = 3
hzh1[hzh2] = 3

[Done] exited with code=0 in 0.181 seconds

如果表达式的求值结果是字符串,可以直接用中括号运算符通过该表达式指定属性名。下面引用出自《JavaScript 语言精粹》一书的一个具有一定技巧性的例子。

这段代码会根据数值的符号而选择调用不同的方法方法调用一词会让人觉得要使用的是点运算符,不过事实上中括号运算符也能被调用

// 引用自《JavaScript语言精粹》一书
// 仅读取数值的整数部分的处理
Math[this < 0 ? 'ceiling' : 'floor'](this));

5.8.3 属性的枚举

可以通过 for in 语句对属性名进行枚举(代码清单 5.10)。通过在 for in 语句中使用中括号运算符,可以间接地实现对属性值的枚举。使用 for each in 语句可以直接枚举属性值。

代码清单 5.10 属性的枚举
var hzh1 = { x:'黄子涵是帅哥!', y:'黄子涵是靓仔!', z:'黄子涵真聪明!' };
for(var key in hzh1) {
    console.log('key = ', key);       // 属性名的枚举
    console.log('val = ', hzh1[key]); // 属性值的枚举
}
[Running] node "e:\HMV\JavaScript\JavaScript.js"
key =  x
val =  黄子涵是帅哥!
key =  y
val =  黄子涵是靓仔!
key =  z
val =  黄子涵真聪明!

[Done] exited with code=0 in 0.262 seconds

属性可以分为直接属性以及继承于原型的属性。for in 语句和 for each in 语句都会枚举继承于原型的属性

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...