本文轉載於:http://www.javashuo.com/article/p-bynemyed-bb.htmljavascript
本篇主要介紹JS中對象的屬性,包括:屬性的分類、訪問方式、檢測屬性、遍歷屬性以及屬性特性等內容。html
1. 介紹:描述屬性的命名方式、查找路徑以及分類java
2. 屬性的訪問方式:介紹'.'訪問方式、'[ ]'中括號訪問方式web
3. 刪除屬性:經過delete關鍵字刪除對象的某個屬性數組
4. 檢測屬性:介紹三種判斷某個屬性是否爲對象的實例屬性:in、obj.hasOwnProperty、obj.propertyIsEnumerableapp
5. 遍歷屬性:介紹三種遍歷對象的屬性:for / in 語句塊、Object.keys(obj) 、Object.getOwnPropertyNames(obj)函數
6. 屬性特性:在Escript5中,增長了屬性特性這一內容,可設置屬性是否可枚舉、可修改等特性this
屬性,特指對象的成員,不僅僅爲'屬性'(字段),也包含了方法。spa
屬性名稱能夠包含英文字符、數字(不能開頭)、特殊符號(如:-、_、$等等)。prototype
但通常使用純英文字符,在特殊狀況下會添加-(橫槓:-webkit-、-moz- )以及 _(下劃線)。
若屬性名稱包含了-(橫槓),屬性訪問方式只能採用'[ ]'中括號訪問:
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; // 此訪問方式會報異常
console.log(o[
'-x'
]);
// => 3 :讀取帶-(橫槓)名稱的屬性,只能採用'[ ]'中括號訪問方式
o[
'-showX'
]();
// => 彈出1 :若方法名稱帶-(橫槓),執行方式很彆扭
|
假設讀取某個對象的屬性x,首先會在此對象的實例屬性中查找。若沒有找到,將會在此對象的原型對象中查找屬性x。若原型對象也沒有屬性x,將繼續查找這個原型對象的原型(假設原型對象含有原型),一直到找到屬性x或者無原型爲止。
對象中的屬性,根據是否自身的可分爲自有屬性和繼承屬性。
① 自有屬性:也可叫實例屬性;指對象自身的屬性。
② 繼承屬性:也可叫原型屬性;指對象從原型中繼承的屬性。
可分爲 ' . '點訪問方式和' [ ] '中括號方法方式 。
說明:若讀取一個不存在的屬性,將返回undefined。若設置一個對象不存在的屬性,將會向對象添加此屬性。
語法:obj.propertyName
說明:屬性名稱必須爲一個標示符(靜態字符串),不能爲變量。
示例:
1
2
|
var
o = {};
o.x =
'1'
;
|
語法:obj[propertyName]
說明:屬性名稱能夠爲一個靜態字符串,也能夠爲一個變量。若爲變量,訪問的屬性爲變量表示的值。
特色:與'.'訪問方式不一樣,'[ ]'中括號訪問方式靈活性很大:可動態訪問(變量指定屬性名)、可訪問包含某些特殊字符的屬性(如:屬性名稱帶'-')
示例:
1
2
3
4
|
var
o = { x: 1, y: 2 };
console.log(o[
'x'
]);
// => 1 :訪問x屬性
var
a =
'y'
;
console.log(o[a]);
// => 2 :訪問的是y屬性(變量a的值)
|
語法:delete obj.propertyName 或者 delete obj[propertyName]
說明: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 :訪問不存在的屬性,返回undefined
o.constructor.prototype.y =
'2'
;
// 在原型對象上添加一個y屬性
console.log(o.y);
// => 2
delete
o.y;
// 刪除繼承屬性y
console.log(o.y);
// => 2 :仍是能夠訪問繼承屬性y
|
檢測對象是否包含某個屬性。
說明:判斷對象是否包含某個屬性,會從對象的實例屬性、繼承屬性裏進行檢測。
語法:propertyName in obj
返回值:
{bool} 判斷對象的實例屬性或繼承是否包含此屬性。
true:對象的實例屬性或繼承屬性包含此屬性;
false:對象的實例屬性或繼承屬性不包含此屬性。
示例:
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爲實例屬性
console.log(
'name'
in
s);
// => true :name爲繼承屬性
console.log(
'address'
in
s);
// => false :address不存在此對象呢,返回false
|
說明:判斷對象是否擁有一個指定名稱的實例屬性,不會檢查繼承屬性。
參數:
①propertyName {string} :屬性名稱。
語法:obj.hasOwnProperty(propertyName)
返回值:
{bool} 判斷對象是否擁有一個指定名稱的實例屬性;此方法不會檢查對象原型鏈中的屬性。
true :屬性爲對象的實例屬性,非繼承。
false :屬性不爲對象的實例屬性。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var
Student =
function
(name) {
this
.name = name;
};
// 給Student的原型添加一個sayHello方法
Student.prototype.sayHello =
function
() {
alert(
'Hello,'
+
this
.name);
}
// 給Student的原型添加一個age屬性
Student.prototype.age =
''
;
var
st =
new
Student(
'張三'
);
// 初始化對象st
console.log(st.hasOwnProperty(
'name'
));
// => true :調用構造函數時,經過this.name附加到實例對象上
console.log(st.hasOwnProperty(
'sayHello'
));
// => false :sayHello方法爲原型上的成員
console.log(st.hasOwnProperty(
'age'
));
// => false :age屬性爲原型上的成員
|
說明:判斷指定名稱的屬性是否爲實例屬性而且是可枚舉的(可用for/in循環枚舉)
參數:
①propertyName {string} :屬性名稱。
語法:obj.propertyIsEnumerable(propertyName)
返回值:
{bool} 判斷屬性是否爲實例屬性而且是可枚舉的(可用for/in循環枚舉),不考慮原型鏈中的成員。
true :屬性爲對象的實例屬性而且是可枚舉的。
false :屬性不爲對象的實例屬性或不可枚舉的。
示例:
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爲實例屬性而且可枚舉
console.log(o.propertyIsEnumerable(
'age'
));
// => false :age爲實例屬性但不可枚舉
console.log(o.hasOwnProperty(
'age'
));
// => true :hasOwnProperty()方法只判斷屬性是否爲實例屬性
|
檢測方式 | 語法 | 檢測屬性的範圍 | 返回值 |
in 運算符 | propertyName in obj | 實例屬性、繼承屬性 | {bool} true:符合條件;fasle:不符合 |
obj.hasOwnProperty(propertyName) | obj.hasOwnProperty(propertyName) | 實例屬性 | {bool} true:符合條件;fasle:不符合 |
obj.propertyIsEnumerable(propertyName) | obj.propertyIsEnumerable(propertyName) | 可枚舉的實例屬性 | {bool} true:符合條件;fasle:不符合 |
即遍歷對象的實例屬性、繼承屬性。
說明:遍歷對象可枚舉的實例屬性和繼承屬性
語法:
for (p in obj) {
// p表示遍歷的屬性名稱
}
示例:
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);
// => 輸出屬性的名稱:x、y、px、py
console.log(o[property]);
// => 採用中括號訪問方式,輸出屬性的值
}
|
說明:返回一個數組,包含對象可枚舉的實例屬性名稱
參數:
①obj {object} :實例對象
返回值:
{Array} 返回一個數組,包含對象可枚舉的實例屬性名稱
示例:
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);
// => 返回一個包含了可枚舉的實例屬性名稱的數組
for
(
var
i = 0, len = propertyArray.length; i < len; i++) {
console.log(propertyArray[i]);
// => 輸出實例屬性名稱:x、y
}
|
說明:返回一個數組,包含對象的全部實例屬性名稱。包括可枚舉和不可枚舉的
參數:
①obj {object} :實例對象
返回值:
{Array} 返回一個數組,包含對象全部實例屬性名稱
與Object.keys()的差異:Object.keys()只返回可枚舉的實例屬性,Object.getOwnPropertyNames()返回全部實例屬性
示例:
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():獲取一個可枚舉的實例屬性名稱的數組
var
propertyArray = Object.keys(o);
for
(
var
i = 0, len = propertyArray.length; i < len; i++) {
console.log(propertyArray[i]);
// => 輸出實例屬性名稱:x
}
// 2.Object.getOwnPropertyNames():獲取一個包含的實例屬性名稱的數組,無論實例屬性是否可枚舉
propertyArray = Object.getOwnPropertyNames(o);
for
(
var
i = 0, len = propertyArray.length; i < len; i++) {
console.log(propertyArray[i]);
// => 輸出實例屬性名稱:x、y
}
|
檢測方式 | 語法 | 遍歷屬性的範圍 | 返回值 |
for / in 語句塊 | for (p in obj) { // p表示遍歷的屬性名稱 } |
可枚舉的實例屬性和繼承屬性 | {String} 屬性的名稱 |
Object.keys(obj) | Object.keys(obj) | 可枚舉的實例屬性 | {Array} 返回一個數組,包含對象可枚舉的實例屬性名稱 |
Object.getOwnPropertyNames(obj) | Object.getOwnPropertyNames(obj) | 包含對象的全部實例屬性名稱。包括可枚舉和不可枚舉的 | {Array} 返回一個數組,包含對象全部實例屬性名稱 |
分爲數據屬性和訪問器屬性;
二者可相互轉換,若轉換後未設置enumerable和configurable特性(兩類屬性描述符都包含這2個特性),將默認採用轉換前的值。
說明:包含屬性的操做特性;如:設置值、是否可枚舉等等
特性名稱 | 描述 | 默認值 |
value | 設置屬性的值 | undefined |
writable | 是否可修改屬性的值;true:可修改屬性的值;false:不可修改屬性的值 | false |
enumerable | 是否可枚舉屬性;true:可枚舉,可經過for/in語句枚舉屬性;false:不可枚舉 | false |
configurable | 是否可修改屬性的特性;true:可修改屬性的特性(如把writable從false改成true);false:不可修改屬性的特性 | false |
默認值:
1)在使用Object.defineProperty、Object.defineProperties 或 Object.create 函數的狀況下添加數據屬性,writable、enumerable和configurable默認值爲false。
2)使用對象直接量建立的屬性,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)經過Object.create建立,屬性特性默認爲false
var
o2 = Object.create(
null
, {
name: {value:
'tom'
}
});
console.log(Object.getOwnPropertyDescriptor(o2,
'name'
));
// => Object {value: "tom", writable: false, enumerable: false, configurable: false}
|
說明:設置屬性的訪問方式;set、get特性等
特性名稱 | 描述 | 默認值 |
get | 屬性的返回值函數 | undefined |
set | 屬性的設置值函數;含有一個賦值參數 | undefined |
enumerable | 是否可枚舉屬性;true:可枚舉,可經過for/in語句枚舉屬性;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 = {};
// 添加一個屬性,並設置爲訪問器屬性
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不能爲純數字
|