类型
六种主要类型(“语言类型”)
- string
- number
- boolean
- null
- undefined
- object
简单基本类型(string,number,boolean,null,undefined)本身并不是对象
typeof null会输出’object‘是因为,不同的对象在底层都表示为二进制,JavaScript中二进制前三为都为0被判断为object
内置对象
- String
- Number
- Boolean
- Object
- Function
- Array
- Date
- RegExp
- Error
和简单基本类型的比较
var str = 'I am a string';
console.log('typeof str', typeof str); // typeof str string
console.log('is str instanceof String', str instanceof String); // is str instanceof String false
var strObj = new String('I am a String');
console.log('typeof strObj', typeof strObj); // typeof strObj object
console.log('is strObj instanceof String', strObj instanceof String); // is strObj instanceof String true
对象的属性名
对象的属性名永远是字符串,如果用其他类型作为属性,也会被转成字符串
var obj = {};
obj[true] = 'foo';
obj[3] = 'bar';
obj[obj] = 'baz';
console.log(obj['true']);
console.log(obj['3']);
console.log(obj.toString()); // [object Object]
console.log(obj['[object Object]']); // obj.toString()的值为[object Object]
数组
数组通过数值下标存储,但是数组也是对象,也可以添加属性。
但当添加一个’2‘字符串数字时,会变成数组下标。
var arry = ['foo'];
console.log('arry.length', arry.length); // arry.length 1
arry.bar = 'bar';
console.log('arry.bar', arry.bar); // arry.bar bar
arry['2'] = 'jsong';
console.log('arry.length', arry.length); // arry.length 3
console.log(arry); // ["foo", empty, "jsong"]
console.log(arry[1]); // undefined
对象拷贝
- 浅拷贝
复制变量的值,引用属性和原来一样,ES6的Object.assgin(…)
function anotherFucntion() {}
var anotherObject = {
c: true
};
var anothterArray = [];
var myObject = {
a: 2,
b: anotherObject,
c: anothterArray,
d: anotherFucntion
};
var newObj2 = Object.assign({}, myObject);
console.log(
'newObj2.a===myObject.a',
newObj2.a === myObject.a,
'newObj2.b===myObject.b',
newObj2.b === myObject.b,
'newObj2.c===myObject.c',
newObj2.c === myObject.c
); // newObj2.a===myObject.a true newObj2.b===myObject.b true newObj2.c===myObject.c true
- 深拷贝
拷贝所有属性
function anotherFucntion() {}
var anotherObject = {
c: true
};
var anothterArray = [];
var myObject = {
a: 2,
b: anotherObject,
c: anothterArray,
d: anotherFucntion
};
// anothterArray.push(anotherObject, myObject);
// 深拷贝
var newObj = JSON.parse(JSON.stringify(myObject));
console.log(
'newObj.a===myObject.a',
newObj.a === myObject.a,
'newObj.b===myObject.b',
newObj.b === myObject.b,
'newObj.c===myObject.c',
newObj.c === myObject.c
); // newObj.a===myObject.a true newObj.b===myObject.b false newObj.c===myObject.c false
属性
从es5开始,属性具备属性的描述
我们创建一个属性,不只包括它的值,还包括writable(可写)、enumerable(可枚举)、configurable(可配置)。默认都是true
var myObject = {
a: 2
};
console.log(Object.getOwnPropertyDescriptor(myObject, 'a')); // {value: 2, writable: true, enumerable: true, configurable: true}
- writeable
可修改的,如果为false则不可以修改这个属性的值,普通模式不会报错,严格模式下回报错。
// 'use strict';
var myObject = {
a: 2
};
console.log(Object.getOwnPropertyDescriptor(myObject, 'a')); // {value: 2, writable: true, enumerable: true, configurable: true}
Object.defineProperty(myObject, 'b', {
value: 3,
writable: false,
configurable: true,
enumerable: true
});
console.log(myObject.b); // 3
myObject.b = 5; // use strict 报错 Uncaught TypeError: Cannot assign to read only property 'b' of object '#<Object>
- configurable
默认true,可以使用defineProperty(…)方法修改属性描述。
false,禁止修改属性描述(报错),禁止删除属性(不报错)
var myObject = { a: 2 };
console.log('a', myObject.a); // a 2
delete myObject.a;
console.log('a', myObject.a); // a undefined
Object.defineProperty(myObject, 'a', {
value: 4,
writable: true,
configurable: false,
enumerable: true
});
console.log('a', myObject.a); // a 4
delete myObject.a;
console.log('a', myObject.a); // a 4
Object.defineProperty(myObject, 'b', {
value: 4,
writable: true,
configurable: false,
enumerable: true
});
myObject.b = 5;
console.log('b', myObject.b);
try {
// 禁止修改
Object.defineProperty(myObject, 'b', {
value: 4,
writable: true,
configurable: true,
enumerable: true
});
} catch (e) {
console.error(e); // Uncaught TypeError: Cannot redefine property: b
- enumerable
默认true,可枚举的
false,不可枚举,在for in 中被忽略
var myObject = { a: 2, b: 3 };
for (let key in myObject) {
console.log(key); // a b
}
Object.defineProperty(myObject, 'a', {
value: 2,
writable: true,
configurable: true,
enumerable: false
});
console.log(myObject.a); // 2
console.log('a' in myObject); // true in检查prototype原型链
console.log(myObject.hasOwnProperty('a')); // true 不检查原型链 只查看自身属性
console.log(myObject.propertyIsEnumerable('a')); // false
console.log(myObject.propertyIsEnumerable('b')); // true
console.log(Object.keys(myObject)); // ["b"] 可枚举的
console.log(Object.getOwnPropertyNames(myObject)); // ["a", "b"] 所有的
for (let key in myObject) {
console.log(key); // b
}
属性的约束
- preventExtensions 禁止扩展
非严格模式下新增属性,静默失败
严格模式下,报错。
// 'use strict';
var myObject = { a: 2 };
Object.preventExtensions(myObject);
myObject.b = 3; // use stric 严格模式下 index.js:193 Uncaught TypeError: Cannot add property b, object is not extensible
console.log(myObject.b); // undefined
- seal 密封
这个方法实际上会在一个现有对象上调用Object.preventExtensions(…) 并把所有现有属性标记为configurable:false,不可以删除属性
// 'use strict';
var myObject = { a: 2 };
Object.seal(myObject);
delete myObject.a; // use stric 严格模式下 index.js:203 Uncaught TypeError: Cannot delete property 'a' of #<Object>
console.log(myObject.a); // 2
- freeze 冻结
这个方法实际上会在一个现有对象上调用Object.seal(…)并把writable设为false。
// 'use strict';
var myObject = { a: 2 };
Object.freeze(myObject);
myObject.a = 3; // use strict 严格模式下 index.js:213 Uncaught TypeError: Cannot assign to read only property 'a' of object '#<Object>'
console.log(myObject.a); // 2
getter和setter
var myObject = {
get a() {
return this._a_;
},
set a(val) {
this._a_ = val;
}
};
Object.defineProperty(myObject, 'b', {
get: function() {
return this.a;
}
});
myObject.a = 2;
console.log('a', myObject.a); // a 2
console.log('b', myObject.b); // b 2