对象扩展

2019-10-08  本文已影响0人  zxhnext

1. 创建对象

1.1 通过对象字面量的形式创建对象

var obj={};//没有任何属性的对象

1.2 通过new Object()创建对象

var obj3=new Object();//创建一个空对象,{}

1.3 通过构造函数的形式创建对象

function Test(){
                
}
var obj4=new Test();

function Test1(num1,num2){
    this.n1=num1;
    this.n2=num2;
}
var obj5=new Test1(5,6);

1.4 通过Object.create()创建对象

var obj6=Object.create({x:1});

2. 对象属性

2.1 查询

//如果属性不确定需要使用[]
function PersonInfo(name,age,sex){
    this.name=name;
    this.age=age;
    this.sex=sex;
}
var person1=new PersonInfo('king',34,'男');
console.log(person1.name+person['sex']);

2.2 删除

//通过delete删除指定属性
delete obj.test;
console.log(obj['test']);
delete obj.username;
console.log(obj['username']);

2.3 遍历

for/in遍历不仅会遍历自身属性,还会遍历原型链中的属性
ECMAScript 对象的属性没有顺序。因此,通过 for-in 循环输出的属性名的顺序是不可预测的。 具体来讲,所有属性都会被返回一次,但返回的先后次序可能会因浏览器而异。
但是,如果表示要迭代的对象的变量值为 null 或 undefined,for-in 语句会抛出错误。 ECMAScript 5 更正了这一行为;对这种情况不再抛出错误,而只是不执行循环体。为了保证最大限度的兼容性,建议在使用 for-in 循环之前,先检测确认该对象的值不是 null 或 undefined。

//通过for/in遍历属性
var obj1={
    x:1,
    y:2,
    test:'this is a test',
    edu:'hello'
};
for(var p in obj1){
    console.log(p+'\n');
}

2.4 添加

function Person(username,age,sex,addr){
    this.username=username;
    this.age=age;
    this.sex=sex;
    this.addr=addr;
    this.info=function(){
        return this.username+this.addr;
    }
}
var p1=new Person('queen',34,'女','上海');
console.log(p1.info());
p1.test='this is a test';
console.log(p1.test);
p1.info1=function(){
    return 'this is a test1111';
};
console.log(p1.info1());

// 通过函数添加属性
function foo(){};
foo.prototype.z=3;
var obj=new foo();
console.log(obj.z); // 3
obj.z=12;
console.log(obj.z); // 12
delete obj.z;
console.log(obj.z); // 3
delete foo.prototype.z;
console.log(obj.z); // undefined

3. 常用API

3.1 Object.defineProperty

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

Object.defineProperty(obj, prop, descriptor)
obj: 要在其上定义属性的对象。
prop: 要定义或修改的属性的名称。
descriptor: 将被定义或修改的属性描述符。

对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一;不能同时是两者。

数据描述符和存取描述符均具有以下可选键值(默认值是在使用Object.defineProperty()定义属性的情况下):

configurable
当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false

enumerable
当且仅当该属性的enumerabletrue时,该属性才能够出现在对象的枚举属性中。默认为 false

数据描述符同时具有以下可选键值

value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为undefined

writable
当且仅当该属性的writabletrue时,value才能被赋值运算符改变。默认为 false

存取描述符同时具有以下可选键值

get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)
默认为 undefined

set
一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
默认为 undefined

var person={
    username:'king',
    sex:'男',
    get age(){
        return 12;
    },
    set age(val){
        console.log('不能设置'+val);
    }
};
console.log(person.username);
console.log(person.age);

var obj={
    x:1,
    y:2,
    z:3,
    get zhouchang(){
        return this.x+this.y+this.z;
    },
    set fbzc(val){
        this.x*=val;
        this.y*=val;
        this.z*=val;
    }
};
console.log(obj.zhouchang);
obj.fbzc=2;
console.log(obj.zhouchang);

3.2 Object.defineProperties

Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

Object.defineProperties(obj, props)

var obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  // etc. etc.
});

3.3 Object.assign

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

Object.assign() 方法只能拷贝源对象的可枚举的自身属性,同时拷贝时无法拷贝属性的特性,而且访问器属性会被转换成数据属性,也无法拷贝源对象的原型,该方法配合

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }

console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }

3. 4 Object.create

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的proto

const person = {
  isHuman: false,
  printIntroduction: function () {
    console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
  }
};

const me = Object.create(person);

me.name = "Matthew"; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten

me.printIntroduction();
// expected output: "My name is Matthew. Am I human? true"

3.5 Object.entries

**Object.entries()**方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。

const object1 = {
  a: 'somestring',
  b: 42
};

for (let [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

// expected output:
// "a: somestring"
// "b: 42"
// order is not guaranteed

3.6 Object.fromEntries

Object.fromEntries() 方法把键值对列表转换为一个对象。

const entries = new Map([
  ['foo', 'bar'],
  ['baz', 42]
]);

const obj = Object.fromEntries(entries);
console.log(obj);
// expected output: Object { foo: "bar", baz: 42 }

3.7 Object.getOwnPropertyDescriptor

Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)

var person={};
Object.defineProperties(person,{
    'username':{
        value:'king',
        writable:true,
        enumerable:true,
        configurable:true
    },
    age:{
        value:12,
        writable:false
    }
});
person.addr='北京';
console.log(person.username);
console.log(person['age']);
console.log(Object.getOwnPropertyDescriptor(person,'username')); // {value: "king", writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(person,'age'));
console.log(Object.getOwnPropertyDescriptor(person,'addr'));

Object.getOwnPropertyDescriptors()方法用来获取一个对象的所有自身属性的描述符。

3.8 getOwnPropertyNames

方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。

3.9 Object.getPrototypeOf

Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。

isPrototypeOf()方法用于测试一个对象是否存在于另一个对象的原型链上。

3.10 通过in检测对象上是否有某个属性

function foo(){};
foo.prototype.z=3;
var obj=new foo();
obj.x=1;
obj.y=2;

console.log('y' in obj);
console.log('z' in obj);
console.log('toString' in obj);

3.11 hasOwnProperty

返回一个布尔值,指示对象自身属性中是否具有指定的属性(只检测自身属性,不能检测继承属性)

console.log(obj.hasOwnProperty('x'));//true
console.log(obj.hasOwnProperty('z'));//false
console.log(obj.hasOwnProperty('toString'));//false

3.12 propertyIsEnumerable

返回一个布尔值,表示指定的属性是否可枚举(只检测自身属性,不能检测继承属性)

3.13 Object.isExtensible

Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

可以通过Object.preventExtensions()方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。
Object.preventExtensions()仅阻止添加自身的属性。但属性仍然可以添加到对象原型。
一旦使其不可扩展,就无法再对象进行扩展。

3.14 Object.seal

Object.seal()方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。

const object1 = {
  property1: 42
};

Object.seal(object1);
object1.property1 = 33;
console.log(object1.property1);
// expected output: 33

delete object1.property1; // cannot delete when sealed
console.log(object1.property1);
// expected output: 33

Object.isSealed()方法可以判断一个对象是否被密封

3.15 Object.freeze

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。

Object.isFrozen()方法检查对象是否被冻结。

冻结只是浅冻结。不能冻结子对象中的属性,如果需要深冻结,需要递归去做深冻结。

// 递归去做深冻结
function deepFreeze(obj){
    var prop,propKey;
    Object.freeze(obj);
    for(propKey in obj){
        prop=obj[propKey];
        if(!obj.hasOwnProperty(propKey)||!(typeof prop==='object')||Object.isFrozen(prop)){
            continue;
        }
        deepFreeze(prop);
    }
}

var obj2={
    internal:{} 
};
deepFreeze(obj2);
obj2.internal.x=1;
console.log(obj2.internal.x);
上一篇下一篇

猜你喜欢

热点阅读