JavaScript 對象屬性介紹本篇主要介紹JS中對象的屬性,包括:屬性的分類(lèi)、訪(fǎng)問(wèn)方式、檢測屬性、遍歷屬性以及屬性特性等內容。
目錄
1.
介紹:描述屬性的命名方式、查找路徑以及分類(lèi)
2.
3.
刪除屬性:通過(guò)delete關(guān)鍵字刪除對象的某個(gè)屬性
4.
檢測屬性:介紹三種判斷某個(gè)屬性是否為對象的實(shí)例屬性:in、obj.hasOwnProperty、obj.propertyIsEnumerable
5.
遍歷屬性:介紹三種遍歷對象的屬性:for / in 語(yǔ)句塊、Object.keys(obj) 、Object.getOwnPropertyNames(obj)
6.
屬性特性:在Escript5中,增加了屬性特性這一內容,可設置屬性是否可枚舉、可修改等特性
1. 介紹
1.1 描述
屬性,特指對象的成員,不單單為'屬性'(字段),也包含了方法。
1.2 命名方式
屬性名稱(chēng)可以包含英文字符、數字(不能開(kāi)頭)、特殊符號(如:-、_、$等等)。
但一般使用純英文字符,在特殊情況下會(huì )添加-(橫杠:-webkit-、-moz- )以及 _(下劃線(xiàn))。
若屬性名稱(chēng)包含了-(橫杠),屬性訪(fǎng)問(wèn)方式只能采用'[ ]'中括號訪(fǎng)問(wèn):
1
2
3
4
5
6
7
8
9
10
11
var o = {
x: 1,
y: 2,
'-x': 3,
'-showX': function () {
alert(this.x);
}
}
// o.-x; // 此訪(fǎng)問(wèn)方式會(huì )報異常
console.log(o['-x']); // => 3 :讀取帶-(橫杠)名稱(chēng)的屬性,只能采用'[ ]'中括號訪(fǎng)問(wèn)方式
o['-showX'](); // => 彈出1 :若方法名稱(chēng)帶-(橫杠),執行方式很別扭
1.3 屬性的查找路徑
假設讀取某個(gè)對象的屬性x,首先會(huì )在此對象的實(shí)例屬性中查找。若沒(méi)有找到,將會(huì )在此對象的原型對象中查找屬性x。若原型對象也沒(méi)有屬性x,將繼續查找這個(gè)原型對象的原型(假設原型對象含有原型),一直到找到屬性x或者無(wú)原型為止。
1.4 屬性的分類(lèi)
對象中的屬性,根據是否自身的可分為自有屬性和繼承屬性。
① 自有屬性:也可叫實(shí)例屬性;指對象自身的屬性。
② 繼承屬性:也可叫原型屬性;指對象從原型中繼承的屬性。
2. 屬性的訪(fǎng)問(wèn)方式
可分為 ' . '點(diǎn)訪(fǎng)問(wèn)方式和' [ ] '中括號方法方式 。
說(shuō)明:若讀取一個(gè)不存在的屬性,將返回undefined。若設置一個(gè)對象不存在的屬性,將會(huì )向對象添加此屬性。
2.1 ' . '點(diǎn)訪(fǎng)問(wèn)方式
語(yǔ)法:obj.propertyName
說(shuō)明:屬性名稱(chēng)必須為一個(gè)標示符(靜態(tài)字符串),不能為變量。
示例:
1
2
var o = {};
o.x = '1';
2.2 ' [ ] '中括號訪(fǎng)問(wèn)方式
語(yǔ)法:obj[propertyName]
說(shuō)明:屬性名稱(chēng)可以為一個(gè)靜態(tài)字符串,也可以為一個(gè)變量。若為變量,訪(fǎng)問(wèn)的屬性為變量表示的值。
特點(diǎn):與'.'訪(fǎng)問(wèn)方式不同,'[ ]'中括號訪(fǎng)問(wèn)方式靈活性很大:可動(dòng)態(tài)訪(fǎng)問(wèn)(變量指定屬性名)、可訪(fǎng)問(wèn)包含某些特殊字符的屬性(如:屬性名稱(chēng)帶'-')
示例:
1
2
3
4
var o = { x: 1, y: 2 };
console.log(o['x']); // => 1 :訪(fǎng)問(wèn)x屬性
var a = 'y';
console.log(o[a]); // => 2 :訪(fǎng)問(wèn)的是y屬性(變量a的值)
3. delete 刪除屬性
語(yǔ)法:delete obj.propertyName 或者 delete obj[propertyName]
說(shuō)明:delete只能刪除對象的自有屬性,不能刪除繼承屬性。
示例:
1
2
3
4
5
6
7
8
9
10
var o = {};
o.x = '1';
console.log(o.x); // => 1
delete o.x;
console.log(o.x); // => undefined :訪(fǎng)問(wèn)不存在的屬性,返回undefined
o.constructor.prototype.y = '2'; // 在原型對象上添加一個(gè)y屬性
console.log(o.y); // => 2
delete o.y; // 刪除繼承屬性y
console.log(o.y); // => 2 :還是可以訪(fǎng)問(wèn)繼承屬性y
4. 檢測屬性
檢測對象是否包含某個(gè)屬性。
4.1 in 運算符
說(shuō)明:判斷對象是否包含某個(gè)屬性,會(huì )從對象的實(shí)例屬性、繼承屬性里進(jìn)行檢測。
語(yǔ)法:propertyName in obj
返回值:
{bool} 判斷對象的實(shí)例屬性或繼承是否包含此屬性。
true:對象的實(shí)例屬性或繼承屬性包含此屬性;
false:對象的實(shí)例屬性或繼承屬性不包含此屬性。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
function People(name) {
this.name = name;
}
function Student(age) {
this.age = age;
}
Student.prototype = new People(); // 設置Student的原型為People對象
var s = new Student(22);
console.log('age' in s); // => true :age為實(shí)例屬性
console.log('name' in s); // => true :name為繼承屬性
console.log('address' in s); // => false :address不存在此對象呢,返回false
4.2 obj.hasOwnProperty(propertyName)
說(shuō)明:判斷對象是否擁有一個(gè)指定名稱(chēng)的實(shí)例屬性,不會(huì )檢查繼承屬性。
參數:
①propertyName {string} :屬性名稱(chēng)。
語(yǔ)法:obj.hasOwnProperty(propertyName)
返回值:
{bool} 判斷對象是否擁有一個(gè)指定名稱(chēng)的實(shí)例屬性;此方法不會(huì )檢查對象原型鏈中的屬性。
true :屬性為對象的實(shí)例屬性,非繼承。
false :屬性不為對象的實(shí)例屬性。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var Student = function (name) {
this.name = name;
};
// 給Student的原型添加一個(gè)sayHello方法
Student.prototype.sayHello = function () {
alert('Hello,' + this.name);
}
// 給Student的原型添加一個(gè)age屬性
Student.prototype.age = '';
var st = new Student('張三'); // 初始化對象st
console.log(st.hasOwnProperty('name')); // => true :調用構造函數時(shí),通過(guò)this.name附加到實(shí)例對象上
console.log(st.hasOwnProperty('sayHello')); // => false :sayHello方法為原型上的成員
console.log(st.hasOwnProperty('age')); // => false :age屬性為原型上的成員
4.3 obj.propertyIsEnumerable(propertyName)
說(shuō)明:判斷指定名稱(chēng)的屬性是否為實(shí)例屬性并且是可枚舉的(可用for/in循環(huán)枚舉)
參數:
①propertyName {string} :屬性名稱(chēng)。
語(yǔ)法:obj.propertyIsEnumerable(propertyName)
返回值:
{bool} 判斷屬性是否為實(shí)例屬性并且是可枚舉的(可用for/in循環(huán)枚舉),不考慮原型鏈中的成員。
true :屬性為對象的實(shí)例屬性并且是可枚舉的。
false :屬性不為對象的實(shí)例屬性或不可枚舉的。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var o = Object.create({}, {
name: {
value: 'tom',
enumerable: true // 可枚舉
},
age: {
value: 22,
enumerable: false // 不可枚舉
}
});
console.log(o.propertyIsEnumerable('name')); // => true :name為實(shí)例屬性并且可枚舉
console.log(o.propertyIsEnumerable('age')); // => false :age為實(shí)例屬性但不可枚舉
console.log(o.hasOwnProperty('age')); // => true :hasOwnProperty()方法只判斷屬性是否為實(shí)例屬性
總結
檢測方式語(yǔ)法檢測屬性的范圍 返回值
in 運算符propertyName in obj實(shí)例屬性、繼承屬性{bool} true:符合條件;fasle:不符合
obj.
hasOwnProperty(propertyName) obj.
hasOwnProperty(propertyName) 實(shí)例屬性{bool} true:符合條件;fasle:不符合
obj.
propertyIsEnumerable(propertyName)obj.
propertyIsEnumerable(propertyName)可枚舉的實(shí)例屬性{bool} true:符合條件;fasle:不符合
5. 遍歷屬性
即遍歷對象的實(shí)例屬性、繼承屬性。
5.1 for / in 語(yǔ)句塊
說(shuō)明:遍歷對象可枚舉的實(shí)例屬性和繼承屬性
語(yǔ)法:
for (p in obj) {
// p表示遍歷的屬性名稱(chēng)
}
示例:
1
2
3
4
5
6
7
var po = { px: 1, py: 2 };
var o = { x: 1, y: 2 };
o.__proto__ = po; // 設置o的原型為po
for (property in o) {
console.log(property); // => 輸出屬性的名稱(chēng):x、y、px、py
console.log(o[property]); // => 采用中括號訪(fǎng)問(wèn)方式,輸出屬性的值
}
5.2 Object.keys(obj)
說(shuō)明:返回一個(gè)數組,包含對象可枚舉的實(shí)例屬性名稱(chēng)
參數:
①obj {object} :實(shí)例對象
返回值:
{Array} 返回一個(gè)數組,包含對象可枚舉的實(shí)例屬性名稱(chēng)
示例:
1
2
3
4
5
6
7
var po = { px: 1, py: 2 };
var o = { x: 1, y: 2 };
o.__proto__ = po; // 設置o的原型為po
var propertyArray = Object.keys(o); // => 返回一個(gè)包含了可枚舉的實(shí)例屬性名稱(chēng)的數組
for (var i = 0, len = propertyArray.length; i < len; i++) {
console.log(propertyArray[i]); // => 輸出實(shí)例屬性名稱(chēng):x、y
}
5.3 Object.getOwnPropertyNames(obj)
說(shuō)明:返回一個(gè)數組,包含對象的所有實(shí)例屬性名稱(chēng)。包括可枚舉和不可枚舉的
參數:
①obj {object} :實(shí)例對象
返回值:
{Array} 返回一個(gè)數組,包含對象所有實(shí)例屬性名稱(chēng)
與Object.keys()的差別:Object.keys()只返回可枚舉的實(shí)例屬性,Object.getOwnPropertyNames()返回所有實(shí)例屬性
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var po = { px: 1, py: 2 };
var o = { x: 1, y: 2 };
// 設置對象o的屬性特性:屬性x為可枚舉,屬性y為不可枚舉
Object.defineProperties(o, {
x: {
enumerable: true
},
y: {
enumerable: false
}
});
o.__proto__ = po; // 設置o的原型為po
// 1.Object.keys():獲取一個(gè)可枚舉的實(shí)例屬性名稱(chēng)的數組
var propertyArray = Object.keys(o);
for (var i = 0, len = propertyArray.length; i < len; i++) {
console.log(propertyArray[i]); // => 輸出實(shí)例屬性名稱(chēng):x
}
// 2.Object.getOwnPropertyNames():獲取一個(gè)包含的實(shí)例屬性名稱(chēng)的數組,不管實(shí)例屬性是否可枚舉
propertyArray = Object.getOwnPropertyNames(o);
for (var i = 0, len = propertyArray.length; i < len; i++) {
console.log(propertyArray[i]); // => 輸出實(shí)例屬性名稱(chēng):x、y
}
總結
檢測方式語(yǔ)法遍歷屬性的范圍 返回值
for /
in 語(yǔ)句塊for (p in obj) {
// p表示遍歷的屬性名稱(chēng)
}可枚舉的實(shí)例屬性和繼承屬性{String} 屬性的名稱(chēng)
Object.
keys(obj)Object.
keys(obj)可枚舉的實(shí)例屬性{Array} 返回一個(gè)數組,包含對象可枚舉的實(shí)例屬性名稱(chēng)
Object.
getOwnPropertyNames(obj)Object.
getOwnPropertyNames(obj)包含對象的所有實(shí)例屬性名稱(chēng)。包括可枚舉和不可枚舉的{Array} 返回一個(gè)數組,包含對象所有實(shí)例屬性名稱(chēng)
6.屬性描述符
分為數據屬性和訪(fǎng)問(wèn)器屬性;
兩者可相互轉換,若轉換后未設置enumerable和configurable特性(兩類(lèi)屬性描述符都包含這2個(gè)特性),將默認采用轉換前的值。
6.1 數據屬性
說(shuō)明:包含屬性的操作特性;如:設置值、是否可枚舉等等
特性名稱(chēng)描述默認值
value設置屬性的值undefined
writable是否可修改屬性的值;true:可修改屬性的值;false:不可修改屬性的值false
enumerable是否可枚舉屬性;true:可枚舉,可通過(guò)for/in語(yǔ)句枚舉屬性;false:不可枚舉false
configurable是否可修改屬性的特性;true:可修改屬性的特性(如把writable從false改為true);false:不可修改屬性的特性false
默認值:
1)在使用Object.defineProperty、Object.defineProperties 或 Object.create 函數的情況下添加數據屬性,writable、enumerable和configurable默認值為false。
2)使用對象直接量創(chuàng )建的屬性,writable、enumerable和configurable特性默認為true。
示例:
1
2
3
4
5
6
7
8
9
10
11
// 1)對象直接量;屬性特性默認為true
var o1 = {
name: 'tom'
};
console.log(Object.getOwnPropertyDescriptor(o1, 'name')); // => Object {value: "tom", writable: true, enumerable: true, configurable: true}
// 2)通過(guò)Object.create創(chuàng )建,屬性特性默認為false
var o2 = Object.create(null, {
name: {value:'tom'}
});
console.log(Object.getOwnPropertyDescriptor(o2, 'name')); // => Object {value: "tom", writable: false, enumerable: false, configurable: false}
6.2 訪(fǎng)問(wèn)器屬性
說(shuō)明:設置屬性的訪(fǎng)問(wèn)方式;set、get特性等
特性名稱(chēng)描述默認值
get屬性的返回值函數undefined
set屬性的設置值函數;含有一個(gè)賦值參數undefined
enumerable是否可枚舉屬性;true:可枚舉,可通過(guò)for/in語(yǔ)句枚舉屬性;false:不可枚舉false
configurable是否可修改屬性的特性;true:可修改屬性的特性(如把writable從false改為true);false:不可修改屬性的特性false
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var obj = {};
// 添加一個(gè)屬性,并設置為訪(fǎng)問(wèn)器屬性
Object.defineProperty(obj, "name", {
get: function () {
return this._name; // get和set里的變量不要使用屬性,如:屬性為name,get和set用的是_name
},
set: function (x) {
if (isNaN(x)) {
this._name = x;
} else {
this._name = 'name不能為純數字';
}
},
enumerable: true,
configurable: true
});
console.log(Object.getOwnPropertyDescriptor(obj, 'name')); // => Object {get: function, set: function, enumerable: true, configurable: true}
obj.name = '12';
console.log(obj.name); // => name不能為純數字