09 Object

Object

在看 ES6 Object的时候,我发觉ES5 Object 的更新我并不是完全知道。

于是觉得还是看一下.

1. __proto__

作为一个 半吊子前端开发人员. 居然不知道这个..

首先这个 MSDN 上的例子

function Rectangle() {
}

var rec = new Rectangle();

if (console && console.log) {
    console.log(rec.__proto__ === Rectangle.prototype);  // Returns true
    rec.__proto__ = Object.prototype;
    console.log(rec.__proto__ === Rectangle.prototype);  // Returns false
}

然后我发现。 貌似这个就是原型链。

只不过以前是隐藏的现在将他公布出来。

他指向构造函数的 prototype.

例如这样

function a() {  };
a.prototype.haha = 10;
a.prototype.haha1 = 11;

var a1 = new a();
h.w(a1.__proto__);
//constructor:a()
//haha:10
//haha1:11
//haha2:20

a1.__proto__.haha2 = 20;

h.w(a1.haha);
h.w(a1.haha1);
h.w(a1.haha2);

h.w(a1.__proto__);
//constructor:a()
//haha:10
//haha1:11
//haha2:20

这边其实是有些疑问的.

比如 haha & haha1 是并不存在于 a1.__proto__ 中.

理论上是 在 a1.__proto__ 中找不到 向上层 prototype 中寻找

但是输出的时候却看得见。

还有就是

在第一次执行 h.w(a1.__proto__); 的时候

确输出了 haha2. 这个应该是在第二次执行的输出的时候才有的啊。

于是在加了一段代码.

function a() {  };
a.prototype.haha = 10;
a.prototype.haha1 = 11;

var a1 = new a();

h.w(a1.__proto__);
h.w(a1.haha2); //undefined.

a1.__proto__.haha2 = 20;

h.w(a1.haha);
h.w(a1.haha1);
h.w(a1.haha2);

h.w(a1.__proto__);

所以我不知道 chrome 在搞什么...

但是能确定的是 __proto__ 就是原型链。

所以.

var o = {}; // o = new Object()

o.__proto__ === Object.prototype

2. Object.assign

var target = { a: 1 };

var source1 = { b: 2 };
var source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

简单说就是合并。

如果有相同的值以后面为准

首先需要注意的是,复制的问题。

多层嵌套以后,他是直接复制的.

    var target4 = {a: 1};
    var target5 = Object.assign({}, target4);

    target5.a = 2;
    h.w(target4); //1

    var target = { a: 1,b:{ b1:1 } };

    var target1 = Object.assign({},target);

    target1.a = 2;
    target1.b.b1 = 2;

    h.w(target.a); //1
    h.w(target.b.b1); //2

所以如果你想复制一个 Object

    var target = { a: 1,b:{ b1:1 } };
    var target1 = Object.assign({},target);

有多层嵌套的肯定不行。

assign 一些特殊的传入值

    try{
        Object.assign(undefined);
        Object.assign(null);
    }
    catch(ex) {
        h.w(ex.name + ":" + ex.message)
        //TypeError:Cannot convert undefined or null to object
    }

    h.w(Object.assign(2)); //Number {[[PrimitiveValue]]: 2}
    h.w(Object.assign("haha")); //String {0: "h", 1: "a", 2: "h", 3: "a", length: 4, [[PrimitiveValue]]: "haha"}
    h.w(Object.assign({a:1})); //Object {a: 1}
    h.w(Object.assign({},true)); //Object {}
    h.w(Object.assign({},"aaa","bbb")); //Object {0: "b", 1: "b", 2: "b"}
    h.w(Object.assign({},10)); //Object {}

3 Object.create

var o = Object.create({a:1}, {
        size: {
            value: "large",
            enumerable: true
        },
        shape: {
            value: "round",
            enumerable: true
        }
    });

h.w(o.a);
h.w(o.size);
h.w(o.shape);

这个是微软的例子

在我的理解已经很说明问题了。

第一个参数 就是原型链继承。

function a() {}
a.prototype = 第一个参数
return new a()

第二个参数我感觉像是 this 不过我不能100%确定..

4. defineProperty & defineProperties

Object.defineProperty(object, propertyname, descriptor)

object

必需。 要在其上添加或修改属性的对象。 这可能是一个本机 JavaScript 对象(即用户定义的对象或内置对象)或 DOM 对象。

propertyname

必需。 一个包含属性名称的字符串。

descriptor

必需。 属性描述符。 它可以针对数据属性或访问器属性。

// Create a user-defined object.
var obj = {};

// Add a data property to the object.
Object.defineProperty(obj, "newDataProperty", {
    value: 101,
    writable: true,
    enumerable: true,
    configurable: true
});

// Set the property value.
obj.newDataProperty = 102;
document.write("Property value: " + obj.newDataProperty + newLine);

value 默认值

writable 是否可写

enumerable 可枚举

configurable 是否可删除

set 写的接口

get 读的接口

大概就这些。

但是里面还是有不少东西值得注意

    var obj = {};

    // Add a data property to the object.
    Object.defineProperty(obj, "newDataProperty", {
        value: 101
    });

    obj.newDataProperty = 100;
    h.w(obj.newDataProperty); //101

比如加上 value 这个默认值, 似乎就会加上 writable = false

修改不了,除非你显示声明了 writable = true

configurable 也就是说 delete obj.newDataProperty

不会再有效了。

enumerable .

    var obj1 = { a:1 };

    // Add a data property to the object.
    Object.defineProperty(obj1, "newDataProperty", {
        value: 101,
        enumerable:false
    });

    for(var key in obj1)
        h.w(key);

set,get

这个比较简单。 就是提供了一个方法而已.

Object.defineProperty(obj, "newAccessorProperty", {
    set: function (x) {
        document.write("in property set accessor" + newLine);
        this.newaccpropvalue = x;
    },
    get: function () {
        document.write("in property get accessor" + newLine);
        return this.newaccpropvalue;
    },
    enumerable: true,
    configurable: true
});

最后 defineProperties

就是多一层 嵌套。 可以一次写多个。

var obj = {};
Object.defineProperties(obj, {
    newDataProperty: {
        value: 101,
        writable: true,
        enumerable: true,
        configurable: true
    },
    newAccessorProperty: {
        set: function (x) {
            document.write("in property set accessor" + newLine);
            this.newaccpropvalue = x;
        },
        get: function () {
            document.write("in property get accessor" + newLine);
            return this.newaccpropvalue;
        },
        enumerable: true,
        configurable: true
    }});

也可以生成好以后 传进去

var obj = {};

var descriptors = { xxx : {value:1 }};

Object.defineProperties(obj, descriptors)

5. Object.freeze(object)

冻结。

其实也就是通过 defineProperty 将除了 enumerable 所有属性设置为false.

6.getOwnPropertyDescriptor && getOwnPropertyDescriptors

    var o = { a:1 };
    var keys = Object.getOwnPropertyDescriptor(o,"a");

    h.w(keys);

    configurable:true
    enumerable:true
    value:1
    writable:true

    Object.freeze(o);
    var keys1 = Object.getOwnPropertyDescriptor(o,"a");

    h.w(keys1);

    configurable:false
    enumerable:true
    value:1
    writable:false

其实就是返回某一个字段 属性。

然后你可以修改了以后 再赋给 字段...

所以说。 给 object 增加了 属性 也不是绝对的安全啊 哈哈哈

getOwnPropertyDescriptors 是ES7的提案。

可以一次返回所有 不用一个一个字段来弄.

7. getOwnPropertyNames

function Pasta(grain, width, shape) {
    // Define properties.
    this.grain = grain;
    this.width = width;
    this.shape = shape;
    this.toString = function () {
        return (this.grain + ", " + this.width + ", " + this.shape);
    }
}

Pasta.prototype.test = "haha";

// Create an object.
var spaghetti = new Pasta("wheat", 0.2, "circle");

// Get the own property names.
var arr = Object.getOwnPropertyNames(spaghetti);
document.write (arr);

// Output:
//   grain,width,shape,toString

上面这个是微软的例子。 就是遍历 属性

很简单,但是他很好玩的是

var o = { a:1 }

Object.defineProperty(o,'haha',{
    enumerable:false,
    value:2
});

var arr1 = Object.getOwnPropertyNames(o);
h.w(arr1);

他无视了 enumerable

8. getPrototypeOf 获取原型链


    var a = function() {}

    h.w(a.prototype == Object.getPrototypeOf(a)); //false

    var b = new a();

    h.w(b.__proto__ == Object.getPrototypeOf(b)) //true

9. Object.is


主要是用来规避

    h.w(+0 === -0);  //true
    h.w(NaN === NaN); //false

    h.w(Object.is(+0,-0)); //false
    h.w(Object.is(NaN,NaN)); //true

其他一样

10. isExtensible isSealed isFrozen


https://msdn.microsoft.com/zh-cn/library/ff806189(v=vs.94).aspx

https://msdn.microsoft.com/zh-cn/library/ff806185(v=vs.94).aspx

https://msdn.microsoft.com/zh-cn/library/ff806188(v=vs.94).aspx

这三个真的木有什么好讲的..

Object.preventExtensions 设置不可扩展

Object.seal 设置是否 configurable

标题三个 就是来检测是否设置了。

11.Object.Keys


感觉和 getOwnPropertyNames 一模一样.

只不过

var o = { a:1 }

Object.defineProperty(o,'haha',{
    enumerable:false,
    value:2
});

h.w(Object.keys(o))

enumerable 有用了

资料

ES5手册

ES5规范之Object增强

上一篇:asp.net中Response对象鱼Request对象


下一篇:asp.net中缓存的使用介绍一