JavaScript 对象(上)
简述:
1、是 javascript 的基本类型
2、是一种复合值,可通过名字访问这些值
3、可看作属性的无序集合,每个属性都是一个名/值对(属性名是字符串或标识符)
4、可以从一个称为原型的对象继承属性(核心特征)
5、是动态的,可新增或删除属性,操作对象是通过引用而不是值
6、属性名可以是包含空字符在内的任意字符串,但对象中不能存在两个或多个同名属性;非严格模式下允许,但后者会覆盖前者的值
注:除了字符串、数字、true、false、null 和 undefined 之外,javascript 中的值都是对象
原型:
1、大部分 javascript 对象都和另一个对象(原型)相关联,每个对象都从原型继承属性
2、可以通过 javascript 代码 object.prototype 获得对其原型对象的引用
3、所有通过对象直接量创建的对象都具有同一个原型对象,使用相同构造函数的对象也具有同一个原型对象
4、所有的内置构造函数(以及大部分自定义的构造函数)都具有一个继承自 object.prototype 的原型
5、一个普通对象的原型可能也有原型,而这一系列链接的原型对象就是”原型链“
创建对象:
1、对象直接量:由若干名/值对组成的映射表,名/值对中间用冒号分隔,名/值对之间用逗号分隔,整个映射表用花括号括起来
// 对象里面的属性值可以是对象 let obj = {"name": "yam", "other": {"weight": "yyy", "high": "xxx"}, "age": 200}; console.log(obj["other"]["high"]); // 输出 xxx
console.log(obj.other.high);
注:对象直接量是一个表达式,这个表达式的每次运算都创建并初始化一个新的对象
2、关键字 new:关键字后跟随一个函数(构造函数)调用,用以初始化一个新创建的对象
let arr = new array(); // 创建一个空数组 let date = new date(); // 创建一个表示当前时间的 date 对象
3、object.create(proto [, more]):创建一个新对象,第一个参数为这个对象的原型,第二个参数可对对象的属性进行进一步描述
// es5 定义的 let obj = object.create({"x": 1, "y": 2}); console.log(obj.x); // 输出 1
属性查询和设置:
// inherit 函数来自 javascript 权威指南 function inherit(p) { if (p == null) throw typeerror(); if (object.create) return object.create(p); let t = typeof p; if (t != "object" && t != "function") throw typeerror(); function f() {}; // 定义一个空构造函数 f.prototype = p; return new f(); // 使用 f() 创建 p 的继承对象 } let o = {}; o.x = 1; let p = inherit(o); p.y = 2; // 属性赋值操作首先会检查原型链,以此判断是否允许赋值 // 赋值时也只是在原始对象上创建属性或对已有属性赋值,而不会修改原型链 // 属性赋值要么失败,要么创建一个属性,要么在原始对象中设置属性 p.x = 3; console.log(o.x); // 输出 1 // 属性访问可以通过点或方括号来操作 console.log(p["x"] + p.y); // 输出 5 // 非严格模式下查询一个不存在的属性并不会报错 console.log(p.z); // 但如果对象本身不存在,那么查询这个不存在的对象的属性就会报错(undefined、null) // console.log(p.z.i); // 报错
注: 1、不能给只读属性重新赋值
2、不能通过同名自有属性覆盖只读的继承属性
3、如果对象 obj 不可扩展,那么不能在 obj 中定义新属性
删除属性:
1、delete 运算符可以删除对象的属性,但只是断开属性和宿主对象的联系,而不会去操作属性中的属性
2、delete 运算符只能删除自有属性,而不能删除继承属性
3、delete 删除成功或者没有任何副作用时,它返回 true;若它后面不是一个属性访问表达式,同样会返回 true!!!
4、不能删除那些可配置性为 false 的属性,但可以删除不可扩展对象的可配置属性,非严格模式下返回 false,严格模式报错
let par = {"q": 10}; let a = object.create(par); a.p = {"x": 1}; let b = a.p; delete a.p; // delete 只断开属性和宿主对象的联系,而不会去操作属性中的属性,可能会造成内存泄漏 console.log(b.x); // 输出 1 console.log(delete a.q); // 什么也没做,输出 true console.log(a.q); // 输出 10 console.log(delete a.t); // 输出 true console.log(delete 20); // 输出 true console.log(delete object.prototype); // 输出 false console.log(delete b); // 删除一个通过变量声明或函数声明(var 和 let)的对象会返回 false
检测属性:
1、运算符 in:左侧为属性名,右侧为对象,若对象的自有属性或继承属性中包含这个属性,则返回 true
2、hasownproperty() 方法:检测给定属性是不是对象的自有属性
3、propertyisenumerable() 方法:检测属性是不是自有属性且可枚举
// 若对象的自有属性或继承属性中包含这个属性,则返回 true let ino = {"x": 1}; console.log("x" in ino); // true console.log("tostring" in ino); // true console.log("y" in ino); // false // 检测给定属性是不是对象的自有属性 console.log(ino.hasownproperty("tostring")); // false // 检测属性是不是自有属性且可枚举 console.log(ino.propertyisenumerable("x")); // true console.log(object.prototype.propertyisenumerable("tostring")); // 不可枚举,false
注:可以使用 "attr !== undefined;" 来判断属性是否存在,但若属性存在且值为 undefined,则只能使用 in
枚举属性:
1、for/in 循环可以在循环体中遍历对象中所有可枚举的属性(包括自有属性和继承属性),并把属性名赋值给循环变量
2、es5 定义了 object.keys(),它返回一个由对象中可枚举的自有属性的名称组成的数组
3、es5 定义了 object.getownpropertynames(),它返回对象的所有自有属性的名称,而不仅仅是可枚举属性
let foro = {"x": 1, "y": 2}; for (let temp in foro) console.log(temp); // 输出 x y console.log(object.keys(foro)); // 输出 ['x', 'y'] console.log(object.getownpropertynames(object.prototype));
上一篇: 隐藏得最深的监考老师