##对象
#对象是一个复杂的原始类型
1. 对象是一个可以自行动态添加属性的类型2. 对象的属性是无序的3. 对象的属性有许多的权限设置(writable enumerable configurable value get/set)4. 对象还有原型链,可以获取原型里的属性值[[proto]]5. 对象还有 [[class]] 表示属于那个种类的 [[extensible]] 是否可以再添加新的属性
#创建对象、原型链的操作
- 对象字面量的方法
对象字面量的方式是以冒号方式将变量名和变量值区分开,以都好分割各个变量,变量可以是各种原始类型。
var foo = {
x: 1,
y: 2,
fn: function() {
},
obj: {
x: 2,
y: 4
}
}
如果对象内部属性还为对象,且对象内部有属性同名,那么 foo.x 取值 会不会取到 obj.x 呢?来看看下面的例子。
console.log(foo.x); // 1
console.log(foo.obj.x); // 2
从而得知答案是不会,内置对象属性不是原型链。只要记住这一点,我们就不会弄错。
- 通过构造函数的创建
1. 通过构造函数创建的对象,都有一个 proto(原型) 有一个 prototype 属性来访问原型
function fnFoo() {}; // 其为构造函数,并不是对象
fnFoo.prototype.z = 2;
var obj = new fnFoo();
2. 如果对象本身没有需要查找的属性,它会一直往原型链上查找,直到找到 null。
// 通过对象来访问 z 属性
console.log(obj.z); // 2 返回原型链上的属性值
3. 对象可以自动添加属性,添加的属性不会影响原型链上的属性。
obj.x = 1; // 给对象属性进行赋值,在非严格条件下,隐式的创建了一个属性。
obj.y = 3;
4. 可以通过 hasOwnProperty() 的方法查找对象本身是否具有该属性。
console.log(obj.hasOwnProperty('z')); // false
5. 可以通过 in 的方式查找对象和对象的原型链上是否有该属性。
console.log('z' in obj); // true
6. 对象通过对已有的属性进行赋值修改,不会影响到原型链上的属性。
obj.z = 5;
console.log(obj.z); // 5
console.log(obj.__proto__.z) // 2 对象访问原型的方式
console.log(fnFoo.prototype.z) // 2 构造函数访问 prototype 属性,即原型。
7. 对象通过 delete 删除属性,只会删除对象本身的属性,不会删除原型链上的属性。
delete obj.z;
console.log(obj.z); // 2
console.log(fnFoo.prototype.z) // 2
8. 总而言之,除了查找,其他对属性的基本操作都不会联系到原型链上的属性。9. 如果访问一个属性返回值为 undefined ,但是不代表对象或者与其原型链上没有该属性。通过 hasOwnProperty() 和 in 的方法来判断这种情况。
console.log(obj.hhh); // undefined
console.log(obj.hasOwnProperty('hhh')); // false
console.log('hhh' in obj); // false
- 通过 Object.create()
这种方法是创建一个该对象的原型,一般为对象。
var obj = Object.create({z:56}); // 修改了原型链
console.log(obj.z); // 56
console.log(obj.__proto__.z); // 56