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 语句都会枚举继承于原型的属性。

原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/272188.html

(0)
上一篇 2022年7月9日
下一篇 2022年7月9日

相关推荐

发表回复

登录后才能评论