var obj = {};
obj.foo = 123;
obj.foo; // 123
const foo = 'bar';
// 简写
const baz = {foo}; // baz = {foo: "bar"}
// 等同于
const baz = {foo: foo};
var obj = { p: "Hello World" };
obj.p; // "Hello World"
obj["p"]; // "Hello World"
with语句的格式如下:with (对象) {
语句;
}
// 例一
var obj = {
p1: 1,
p2: 2,
};
with (obj) {
p1 = 4;
p2 = 5;
}
// 等同于
obj.p1 = 4;
obj.p2 = 5;
// 例二
with (document.links[0]) {
console.log(href);
console.log(title);
console.log(style);
}
// 等同于
console.log(document.links[0].href);
console.log(document.links[0].title);
console.log(document.links[0].style);
delete命令用于删除对象的属性,删除成功后返回true。
var obj = { p: 1 };
Object.keys(obj); // ["p"]
delete obj.p; // true
obj.p; // undefined
Object.keys(obj); // []
in 运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值),true,否则返回false。它的左边是一个字符串,表示属性名,右边是一个对象。var obj = { p: 1 };
"p" in obj; // true
"toString" in obj; // true
Object.keys:查看一个对象本身的所有属性var obj = { key1: 1, key2: 2};
Object.keys(obj); // ['key1', 'key2']
Object.getOwnPropertyNames:查看一个对象本身的所有属性
length属性是不可枚举的属性,所以只出现在Object.getOwnPropertyNames方法的返回结果中。for...in 循环用来遍历一个对象的全部属性。
for...in循环遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。toString属性,但是for...in循环不会遍历到这个属性。var obj = { a: 1, b: 2, c: 3 };
for (var i in obj) {
console.log("键名:", i); // 键名: a // 键名: b // 键名: c
console.log("键值:", obj[i]); // 键值: 1 // 键值: 2 // 键值: 3
}
ES6 一共有 5 种方法可以遍历对象的属性。
for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。Reflect.ownKeys返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]
上面代码中,Reflect.ownKeys方法返回一个数组,包含了参数对象的所有属性。这个数组的属性次序是这样的,首先是数值属性2和10,其次是字符串属性b和a,最后是 Symbol 属性。
{
value: 123,
writable: false,
enumerable: true,
configurable: false,
get: undefined,
set: undefined
}
let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
// {
// value: 123,
// writable: true,
// enumerable: true,
// configurable: true
// }
value 是该属性的属性值,默认为undefined。
writable 是一个布尔值,表示属性值(value)是否可改变(即是否可写),默认为true。
enumerable是一个布尔值,表示该属性是否可遍历,默认为true。如果设为false,会使得某些操作(比如for...in循环、Object.keys())跳过该属性。
configurable是一个布尔值,表示属性的可配置性,默认为true。如果设为false,将阻止某些操作改写属性描述对象,比如无法删除该属性,也不得改变各种元属性(value属性除外)。也就是说,configurable属性控制了属性描述对象的可写性。
get是一个函数,表示该属性的取值函数(getter),默认为undefined。
set是一个函数,表示该属性的存值函数(setter),默认为undefined。
Object.getOwnPropertyDescriptor()方法可以获取属性描述对象。它的第一个参数是目标对象,第二个参数是一个字符串,对应目标对象的某个属性名。
Object.getOwnPropertyNames方法返回一个数组,成员是参数对象自身的全部属性的属性名,不管该属性是否可遍历。
对象的每个属性都有一个描述对象(Descriptor),描述对象的“可枚举性”enumerable属性为false,表示某些操作会忽略当前属性。
下面四个操作会忽略enumerable为false的属性。
for...in循环:只遍历对象自身的和继承的可枚举的属性。返回继承的属性Object.keys():返回对象自身的所有可枚举的属性的键名。忽略继承的属性,只处理对象自身的属性JSON.stringify():只串行化对象自身的可枚举的属性。忽略继承的属性,只处理对象自身的属性Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。忽略继承的属性,只处理对象自身的属性,ES6 新增的实际上,引入“可枚举”(enumerable)这个概念的最初目的,就是让某些属性可以规避掉for...in操作,不然所有内部属性和方法都会被遍历到。比如,对象原型的toString方法,以及数组的length属性,就通过“可枚举性”,从而避免被for...in遍历到。
let obj = {foo: 123}; // obj = {foo: 123}
let obj = {};
obj.foo = 123; // obj = {foo: 123}
const foo = 'bar';
const obj = {foo}; // obj = {foo: "bar"}
将目标对象自身的所有可遍历的(enumerable)、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
解构赋值要求等号右边是一个对象
解构赋值必须是最后一个参数
变量必须与属性同名,才能取到正确的值,顺序不对没事
真正被赋值的是属性后面的变量,而不是属性。
默认:let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
改名:const { x, y: z } = { x: 1, y: 2 }
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 } 获取等号右边的所有尚未读取的键(`a`和`b`),将它们连同值一起拷贝过来
...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。v = {...v, xxx: y}let x = 5;
let z = { a: 3, b: 4 };
let n = { x, ...z };
n // {c: 5, a: 3, b: 4}
注意,解构赋值的拷贝是浅拷贝,即如果一个键的值是复合类型的值(数组、对象、函数)、那么解构赋值拷贝的是这个值的引用,而不是这个值的副本。
let obj = { a: { b: 1 } };
let { ...x } = obj;
obj.a.b = 2;
x.a.b // 2
// `x`是解构赋值所在的对象,拷贝了对象`obj`的`a`属性。`a`属性引用了一个对象,修改这个对象的值,会影响到解构赋值对它的引用。
let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
let { ...o3 } = o2;
o3 // { b: 2 }
o3.a // undefined
// 上面代码中,对象`o3`复制了`o2`,但是只复制了`o2`自身的属性,没有复制它的原型对象`o1`的属性。
{ ...['a', 'b', 'c'] } // {0: "a", 1: "b", 2: "c"}
{...'hello'} // {0: "h", 1: "e", 2: "l", 3: "l", 4: "o"}
{...{}, a: 1} // { a: 1 }
{...1} // {} // 等同于 {...Object(1)} 等同于 {...Number{1}}
{...true} // {} // 等同于 {...Object(true)}
{...undefined} // {} // 等同于 {...Object(undefined)}
{...null} // {} // 等同于 {...Object(null)}
Object.assign()方法。let ab = { ...a, ...b };
// 等同于
let ab = Object.assign({}, a, b);
let aWithOverrides = { ...a, x: 1, y: 2 };
// 等同于
let aWithOverrides = { ...a, ...{ x: 1, y: 2 } };
// 等同于
let x = 1, y = 2, aWithOverrides = { ...a, x, y };
// 等同于
let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 });
上面代码中,a对象的x属性和y属性,拷贝到新对象后会被覆盖掉。
这用来修改现有对象部分的属性就很方便了。
let newVersion = {
...previousVersion,
name: 'New Name' // Override the name property
};
上面代码中,newVersion对象自定义了name属性,其他属性全部复制自previousVersion对象。
如果把自定义属性放在扩展运算符前面,就变成了设置新对象的默认属性值。
let aWithDefaults = { x: 1, y: 2, ...a };
// 等同于
let aWithDefaults = Object.assign({}, { x: 1, y: 2 }, a);
// 等同于
let aWithDefaults = Object.assign({ x: 1, y: 2 }, a);
var o1 = {};
var o2 = o1;
o1.a = 1;
o2.a; // 1
o2.b = 2;
o1.b; // 2
JSON.parse(JSON.stringify(config.data)) 转换为字符串再转换为对象后赋值类似的,在 vue 中,变量赋值,修改变量会导致原始数据也同步发生改变
let a = JSON.parse(JSON.stringify(this.file));
Object对象,即那些对象都是Object的实例。Object对象的原生方法分成两类
Object静态方法:直接定义在Object对象的方法Object实例方法:定义在Object原型对象Object.prototype上的方法。它可以被Object实例直接使用// 静态方法
Object.print = function (o) {
console.log(o);
};
// 实例方法
Object.prototype.print = function () {
console.log(this);
};
var obj = new Object(); //实例`obj`直接继承了`Object.prototype`的属性和方法
obj.print(); // Object
__proto__属性(前后各两个下划线),用来读取或设置当前对象的原型对象(prototype)。目前,所有浏览器(包括 IE11)都部署了这个属性。Object() 将任意值转为对象: Object本身是一个函数,可以当作工具方法使用,将任意值转为对象。Object() 构造函数: Object不仅可以当作工具函数使用,还可以当作构造函数使用,即前面可以使用new命令。(1)对象属性模型的相关方法
Object.keys:查看一个对象本身的所有属性,返回一个包含所有给定对象自身可枚举属性名称是数组Object.getOwnPropertyNames:查看一个对象本身的所有属性,返回一个数组,成员是参数对象自身的全部属性的属性名,不管该属性是否可遍历。
length属性是不可枚举的属性,所以只出现在Object.getOwnPropertyNames方法的返回结果中。Object.getOwnPropertyDescriptor():获取某个属性的描述对象。它的第一个参数是目标对象,第二个参数是一个字符串,对应目标对象的某个属性名。Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象。ES2017 引入Object.defineProperty():通过描述对象,定义某个属性。给对象添加一个属性并指定该属性的配置Object.defineProperties():通过描述对象,定义多个属性。Object.hasOwn():也可以判断是否为自身的属性。(2)控制对象状态的方法
Object.preventExtensions():防止对象扩展。Object.isExtensible():判断对象是否可扩展。Object.seal():禁止对象配置。Object.isSealed():判断一个对象是否可配置。Object.freeze():冻结一个对象。Object.isFrozen():判断一个对象是否被冻结。(3)原型链相关方法
Object.is() 比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致Object.assign() 通过复制一个或者多个对象,创建一个对象,浅拷贝,方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。Object.values() 返回给定对象自身可枚举属性的键值的数组Object.create():该方法可以指定原型对象和属性,返回一个新的对象。Object.entries():方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。Object.getPrototypeOf():获取对象的Prototype对象。该方法与Object.setPrototypeOf方法配套,用于读取一个对象的原型对象。Object.setPrototypeOf:方法的作用与__proto__相同,用来设置一个对象的原型对象(prototype),返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。Object.assign(obj1, obj2, obj3)
Object.prototype.valueOf():返回当前对象对应的值。Object.prototype.toString():返回当前对象对应的字符串形式。Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式。Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型。返回一个布尔值,看当前对象是否在指定对象的原型链上Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举。Object.prototype.hasPrototypeProperty():从字面上就可以知道是检测原型对象上的属性。对象位于原型中,则返回true。Object.prototype.toString()
toString方法,覆盖了Object.prototype.toString方法。[1, 2, 3].toString(); // "1,2,3"
var obj = {};
obj.toString(); // "[object Object]"
toString方法,结果返回一个字符串object Object,其中第二个Object表示该值的构造函数。toString方法,覆盖掉Object.prototype.toString方法,所以为了得到类型字符串,最好直接使用Object.prototype.toString方法。通过函数的call方法,可以在任意值上调用这个方法,帮助我们判断这个值的类型。Object.prototype.toString.call(value);
不同数据类型的Object.prototype.toString方法返回值如下。
[object Number]。[object String]。[object Boolean]。[object Undefined]。[object Null]。[object Array]。[object Arguments]。[object Function]。[object Error]。[object Date]。[object RegExp]。[object Object]。这就是说,Object.prototype.toString可以看出一个值到底是什么类型。
Object.prototype.toString.call(2); // "[object Number]"
Object.prototype.toString.call(""); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(Math); // "[object Math]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"