Skip to content

Instantly share code, notes, and snippets.

@hjzheng
Last active March 13, 2016 05:52
Show Gist options
  • Save hjzheng/87d9baf58bc70fdec425 to your computer and use it in GitHub Desktop.
Save hjzheng/87d9baf58bc70fdec425 to your computer and use it in GitHub Desktop.

对象

对象的属性特性 (property attribute)

  • 可写 (writable attribute), 表明是否可以设置该属性的值
  • 可枚举 (enumerable attribute), 表明是否可以通过for/in循环返回该属性
  • 可配置 (configurable attribute),表明是否可以删除或修改该属性

对象特性 (object attribute)

  • 对象的原型 (prototype) 指向另外一个对象,本对象的属性继承自它的原型对象
  • 对象的类 (class)是一个标识对象类型的字符串
  • 对象的扩展标记 (extensible flag)指明了是否可以向该对象添加新属性

创建对象

1.三种方式

  • 对象字面量方式
  • 通过new方式创建
  • Object.create() ES5
// 这样创造出来的对象是和字面量和new Object()的方式是一样的,都继承自Object.prototype
var o = Object.create(Object.prototype);
Object.getPrototypeOf(o); // 返回 Object.prototype , 包含像 toString(), valueOf等方法

// 创建一个空对象,不继承任何对象
var o1 = object.create(null);
Object.getPrototypeOf(o1); // 返回null

2.原型继承

function inherit(p) {
 if(p == null) throw TypeError();
 if(Object.create) return Object.create(p);
 var t = typeof p;
 if(t !== "object" && t !== "function") throw TypeError();
 function F(){};
 F.prototype = p;
 return new F();
}

var o1 = Object.create({x:1})Object.x = 1;var o2 = Object.create(Object.prototype) 的区别??? (注意 __proto__

** __proto__ is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build __proto__ when you create an object with new: **

( new Foo ).__proto__ === Foo.prototype
( new Foo ).prototype === undefined

3.对象自有属性和继承属性(继承自原型上的属性) 如果对象自有属性和继承属性同名,会访问自有属性,所以我们可以有选择的覆盖继承属性,而不修改继承属性。

检测属性

  • in运算符
  • hasOwnProperty()
  • propertyIsEnumerable()
var o = {x:1};
"x" in o; // true: “x”是o的属性
"y"in o; //false: "y"不是o的属性
"toString" in o; //true o继承 toString属性
var o = {x:1};
o.hasOwnProperty("x"); //true: o有一个自有属性x
o.hasOwnProperty("y"); //false: y不是o的自有属性
o.hasOwnProperty("toString") //false toString是继承的属性

propertyIsEnumerable是hasOwnProperty()的增强版,只有检测到是自有属性且这个属性可以被枚举

枚举属性

for/in循环可以遍历对象中所有可以枚举的属性(包括自有属性和继承的属性)

for(p in o){
 if(!o.hasOwnProperty(p)) continue; //跳过继承属性
} 

for(p in o){
 if(typeof o[p] === 'function') continue; //跳过函数
} 

P131 用来枚举对象的工具函数 lodash中是否有对应的方法

ES5 Object.keys 返回对象中可枚举的自有属性的名称组成的数组 ES5 Object.getOwnPropertyNames 返回所有自有属性的名称,而不仅仅是可枚举的

属性getter和setter

属性的特性

数据的4个特性 值(value) 可写性(writable) 可枚举性(enumerable) 可配置性(configurable) 两类属性:

  • 数据属性-> 值 可写性 可枚举性 可配置性
  • 存取器属性-> get set 可枚举性 可配置性

可以通过 Object.getOwnPropertyDescriptor 查找属性特性的描述符 改方法只能得到自有属性的描述符,如果需要进一步查找继承属性的描述符 需要使用 Object.getPrototypeOf() 方法遍历原型链

Object.getOwnPropertyDescriptor({x:1}, 'x'); 
//Object {value: 1, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(Object, 'prototype');
//Object {value: Object, writable: false, enumerable: false, configurable: false}

var o = {
   n: 0,
   get num(){
     return n; 
   }, 
   set num(value){
     this.n = value;
   }
}
Object.getOwnPropertyDescriptor(o, 'num');
/*
configurable: true
enumerable: true
get: num()
set: num(value)
__proto__: Object
*/

如果想要修改对象属性的描述符,需要使用Object.defineProperty()方法

var o = {};
Object.defineProperty(o, "x", {value: 1, writable: true, enumerable: false, configurable: true});
o.x
Object.keys(o) //[]

//修改让其变成只读
Object.defineProperty(o, "x", {writable: false});
o.x = 10; //修改失败,但不报错,严格模式下报错
o.x //1

Object.defineProperties()

var p = Object.defineProperties({},{
   x: {value: 1, writable: true, enumerable: false, configurable: true},
   y: {value: 1, writable: true, enumerable: false, configurable: true},
   r: {
        get: function(){
            return Math.sqrt(this.x*this.x + this.y*this.y);
        },
        enumerable: false, 
        configurable: true
      }
});

p.r;

Object.defineProperty 和 Object.defineProperties 的规则 违反规则使用会抛出类型错误

  • 如果对象是不可扩展的,则可以编辑已有的自有属性,但是不能给它添加新属性
  • 如果属性是不可配置的,则不能修改它的可配置性和可枚举性
  • 如果存取器属性是不可配置的,则不能修改其getter和setter方法,也不能将它转换为数据属性
  • 如果数据属性是不可配置的,则不能将它转换成为存取器属性
  • 如果数据属性是不可配置的,则不能将它的可写性从false修改为true,但是可以从true改为false
  • 如果数据属性是不可配置的且不可写的,则不能修改它的值。然而可配置但不可写属性值是可以修改的。

复制属性的特性

Object.defineProperty(Object.prototype, "extend", {
    writable: true, 
    enumerable: false, 
    configurable: true,
    value: function(o){
        var names = Object.getOwnPropertyNames(o);
        for(var i=0; i<names.length; i++){
            if(names[i] in this) continue;
            var desc = Object.getOwnPropertyDescriptor(o, names[i]);
            Object.defineProperty(this, names[i], desc);
        }
    }
});

对象的可扩展性

Object.seal(obj)
Object.frezz()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment