对象密封的4种方法
const obj={
get foo(){
},
set foo() {
//SyntaxError: Setter must have exactly one formal parameter.
/*set方法必须有参数*/
}
}
console.log(obj.foo);
const obj = {
get foo() {
},
set foo(x) {
}
}
console.log(obj.foo);//undefined
/*通过对象.属性的方式并不能获取当前的取值get(getter)函数和储存set(setter)函数*/
const obj = {
get foo() {
},
set foo(x) {
}
}
console.log(obj.foo);//undefined
console.log(obj);
const obj = {
get foo() {
},
set foo(x) {
}
}
console.log(obj.foo);//undefined
// console.log(obj);
console.log(Object.getOwnPropertyDescriptor(obj,'foo'));
const obj = {
get foo() {
},
set foo(x) {
}
}
/* console.log(obj.foo);//undefined
// console.log(obj);
console.log(Object.getOwnPropertyDescriptor(obj,'foo'));*/
var descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
console.log(descriptor);
console.log(descriptor.get.name)//get foo
console.log(descriptor.get)//
console.log(descriptor.set.name)//set foo
console.log(descriptor.set)//
var obj = {a: 2};
console.log(Object.prototype);
1.对象常量:configurable:fase writeable:false; 不可删除,不可修改;
还需要一个不可以添加,不可以扩展
var obj = {a: 2};
// var test=Object.preventExtensions(obj);/*让obj对象不能扩展*/
Object.preventExtensions(obj);/*让obj对象不能扩展*/
// console.log(test===obj);//true
obj.b=3;
console.log(Object.isExtensible(obj));//false 不可扩展 true可扩展
console.log(obj);//{a: 2}
严格模式下会报错
var obj = {a: 2};
obj.b = 3;//属性描述符,全都是true
/*{ value: 3, writable: true, enumerable: true, configurable: true }
* 属性描述符,全都是true*/
/*Object.defineProperty(obj, 'b', {
value: 6
})*/
/*属性描述符,默认是false
* { value: 6, writable: false, enumerable: false, configurable: false }
*/
console.log(Object.getOwnPropertyDescriptor(obj, 'b'));
console.log(obj);//{a: 2}
2.preventExtensions禁止对象扩展;false不可扩展 true可扩展
3.seal 对象的密封 true密封的 false不密封的
本质上是在做一个调用prevent extension这件事情,它会有一个循环操作,把循环到的属性,把属性配置成configurable等于false
4.Object.freeze();
time36min
kl
相等的扩展
/*相等运算符*/
console.log(NaN==NaN);//false
console.log(+0==-0);//true
/*严格相等运算符*/
console.log(NaN===NaN);//false
/*这种情况并不合理,如果判断两个非数字,一般是转换成字符串再去判断的*/
console.log(+0===-0);//true
/*===会调用 底层的一个叫做sameValue的算法,来判断,不是方法,也会出现NaN===NaN false的现象*/
/*==会进行转换,隐式转换*/
console.log(Object.is(NaN,NaN));//true
console.log(Object.is(+0,-0));//false
/*Object.is(val1,val2)底层调用的还是===,只不过以上两个的结果与===不同,其它的结果相同*/
Object.assign()
用来合并一个对象的,
es5 extend()类似的方法
Object.assign(tar,…sourses)
let obj = {a: 1};
let tar = {};
let copy=Object.assign(tar,obj);
console.log(copy)//{ a: 1 }
console.log(copy===obj);//false
console.log(copy===tar);//true
所以一般就是tar不用赋值,因为接收的变量,方法返回值就是经过改变的第一个变量的值,的地址
let obj = {a: 1};
let tar = {};
Object.assign(tar,obj);
//let copy=Object.assign(tar,obj);
console.log(tar)//{ a: 1 }
const tar = {a: 1, b: 1};
const tar2 = {b: 2,c : 2};
const tar3 = {c: 3};
Object.assign(tar, tar2, tar3);//{ a: 1, b: 2, c: 3 }
/*类似于以下代码*/
// Object.assign(Object.assign(tar, tar2), tar3);//{ a: 1, b: 2, c: 3 }
console.log(tar);//{ a: 1, b: 2, c: 3 }
/*后面的会覆盖前面的*/
Object.assign(undefined, {a: 1});
//TypeError: Cannot convert undefined or null to object
Object.assign(null, {a: 1});
// TypeError: Cannot convert undefined or null to object
var test=Object.assign(1, {a: 1});
// var test=Object.assign(new Number(1), {a: 1});
console.log(test);//[Number: 1] { a: 1 }
把1通过new Number(1)转换成对象
var test=Object.assign('1', {a: 1});
var test=Object.assign(new String('1'), {a: 1});
console.log(test);//String{'1', a: 1}
var test=Object.assign({a: 1},undefined);
console.log(test);//{a: 1}
var test=Object.assign({a: 1},1);
console.log(test);//{a: 1}
var test=Object.assign({a: 1},'123');
console.log(test);//{0: '1', 1: '2', 2: '3', a: 1}
var test=Object.assign({a: 1},'1');
console.log(test);//{0: '1', a: 1}
var test=Object.assign({a: 1},true);
console.log(test);//{a: 1}
当前的参数如果能够转成对象的话,注意对象里面的属性是否是可枚举性的,可枚举性是否为真,为真才能完成拷贝
对第二个参数应该注意以上内容
const test1 = 'abc';
const test2 = true;
const test3 = 10;
const obj = Object.assign({}, test1, test2, test3);
console.log(obj);//{0: 'a', 1: 'b', 2: 'c'}
console.log(new Object('abc'));
console.log(new Object('abc'));
console.log(new Boolean(true));
console.log(new Number(10));
const test1 = 'abc';
const test2 = true;
const test3 = 10;
// const obj = Object.assign({}, test1, test2, test3);
const obj = Object.assign({}, test1);//{0: 'a', 1: 'b', 2: 'c'}
// const obj = Object.assign({}, test2);//{}
// const obj = Object.assign({}, test3);//{}
console.log(obj);//{0: 'a', 1: 'b', 2: 'c'}
可以枚举的才可以, enumerable: true,这个属性默认是false
继承属性,和不可枚举属性 不能拷贝
var obj = Object.create({foo: 1}, {
bar: {
value: 2
},
baz: {
value: 3,
enumerable: true
}
})
console.log(obj);//{baz: 3, bar: 2}
var copy=Object.assign({},obj);
console.log(copy);//{baz: 3}
symbol
var a = Symbol();
var b = Symbol();
console.log(a,b);//Symbol() Symbol()
console.log(a===b);//false
console.log(a==b);//false
var a = Symbol('a');
var b = Symbol('a');
console.log(a,b);//Symbol(a) Symbol(a)
console.log(a===b);//false
console.log(a==b);//false
可以通过symbol方法生成一个类似于字符串的一个原始类型,可以先看作一个值不会重复的字符串
symbol返回的字符串都不会重复
var test = Object.assign({a: 'b'}, {[Symbol('c')]:'d'});
console.log(test);
通过assign,也可以合并symbol生成的属性,symbol类型的属性也能进行拷贝
深拷贝还是浅拷贝,浅拷贝
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
console.log(obj2);//浅拷贝的对象 是浅拷贝
const target = {a: {b: 'c', d: 'e'}};
const sourse = {a: {b: 'hello'}};
/*a:{..}把a:{..}里面的内容全部替换掉了*/
Object.assign(target,sourse);
console.log(target);//同名属性的替换问题
var a = Object.assign([1, 2, 3], [4, 5]);
console.log(a);//[4, 5, 3]
var a = Object.assign([1, 2, 3], [4, 5]);
console.log(a);//[4, 5, 3] 数组的替换
const sourse = {
get foo() {
return 1;
}
}
const target = {};
Object.assign(target, sourse);
console.log(target);//{foo: 1}
这个拷贝方式并不合适,不好
只是把foo属性值,把返回的值1拿到并没有把get foo的一切都拿到,一会会有解决方法
通过assign方法扩充Person原型上的属性
var age=1;
function Person() {
}
Object.assign(Person.prototype,{
eat(){
},
age,
})
console.log(Person.prototype)
console.log(Person)
// const default1 = {//可以
const DEFAULT = {//可以
// const default = {//Uncaught SyntaxError: Unexpected token 'default'
url: "www.baidu.com",
port: 7070
}
function test(option) {
// option = Object.assign({}, DEFAULT);
option = Object.assign({}, DEFAULT, option);
console.log(option);
}
test({url: {port: 8080}})//{url: 'www.baidu.com', port: 7070}
/*默认值,修改默认值,把默认url整个顶掉*/
defineProperties添加定义多个属性
var obj = {};
Object.defineProperties(obj, {
a: {
value: true,
writable: true
},
b:{
value: 'hello',
writable: false
}
})
console.log(obj);
console.log(Object.getOwnPropertyDescriptors(obj));
assign与set:assign不能拷贝set,只能拷贝set返回的值
const sourse = {
set foo(value) {
console.log(value);
}
}
const tar = {};
Object.assign(tar,sourse);
console.log(tar);
assign不能给set赋值
解决方法,可运算属性完成赋值
getOwnPropertyDescriptors、defineProperties这两个方法主要是为了解决这个问题而存在的
const sourse = {
set foo(value) {
console.log(value);
}
}
const tar = {};
// Object.assign(tar, sourse);
Object.defineProperties(tar,Object.getOwnPropertyDescriptors(sourse));
console.log(tar);//
console.log(Object.getOwnPropertyDescriptor(tar,'foo'));
这样不行,assign拷贝不了get set
const sourse = {
set foo(value) {
console.log(value);
}
}
const tar = {};
Object.assign(tar, sourse);
// Object.defineProperties(tar,Object.getOwnPropertyDescriptors(sourse));
console.log(tar);//
console.log(Object.getOwnPropertyDescriptor(tar,'foo'));
实现浅拷贝
var obj = {a: 1, b: 2, c: 3};
const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
/*Object.getPrototypeOf(obj)得到obj的原型
*Object.getOwnPropertyDescriptors(obj)获取obj上面所有属性,克隆obj上面的属性 */
console.log(clone);//{a: 1, b: 2, c: 3}
封装
var obj = {a: 1, b: 2, c: 3};
// const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
/*Object.getPrototypeOf(obj)得到obj的原型
*Object.getOwnPropertyDescriptors(obj)获取obj上面所有属性,克隆obj上面的属性 */
const clone = (obj) => Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
)
// console.log(clone);//{a: 1, b: 2, c: 3}
console.log(clone(obj));//{a: 1, b: 2, c: 3}
这是新增api,但不讲不行,用的相对少一点,但解决方案是唯一的
部署对象
1. const obj = {a:1}
2. const obj = Object.create(prototype);
obj.foo = 123;
3. const obj = Object.assign(Object.create(prototype),{foo:123});
4. const obj = Object.create(prototype,Object.getOwnPropertyDescriptors({
foo:123
}));