Javascript对象学习

javascript对象

动态:可新增、删除属性;
但常来模拟静态对象以及静态类型语言中的结构体(struct),有时也做字符串的集合。
除了字符串、数字、true、false、null、undefined之外,其他的javascript都是对象。尽管字符串、数字、布尔值不是对象,行为和不可变对象相似。

方法:
    create、set、query、delete、test、enumerate
属性特征:
    1.可写:表明是否可设置改属性的值
    2.可枚举:表明是否可以通过for/in循环返回该属性
    3.可配置:表明是否可以删除或修改该属性
  注:ECMAScript5之前,代码给对象创建的所有属性都是可枚举的。之后有改变

对象特性:
    1.对象的原型(protype)指向另一个对象,本对象的属性继承与它的原型对象
    2.对象的类(class)是一个表示对象类型的字符串
    3.对象的扩展标记(exensible flag)指明了是否可以向该对象添加新属性

三类对象和两类属性:
    1.内置对象(native object):ECMAScript规范定义的对象或类。例如:数组、函数、日期、正则表达式
    2.宿主对象(host object):javascript解释器锁嵌入的宿主环境,例如:web浏览器定义的。网页结果中的htmlelement都是宿主对象。宿主环境定义的方法都可以看做普通javascript的函数对象,那么宿主对象也可以当做内置对象
    3.自定义对象(user-defind object):由运行的javascript代码创建的对象
    4.自有属性(own property):直接在对象中定义的属性
    5.继承属性(inherited property):在对象的原型对象中定义的属性

原型:

所有通过对象直接量创建的对象都具有同一个原型对象,并可以通过JavaScript代码Object.prototype获得对原型对象的引用。
     new Object() ---> Object.prototype
     new Array() ---> Array.prototype

Object.create()

静态函数,不提供给某个对象调用,只需传入所需原型对象即可
    var test = Object.create(Object.prototype); //和{}、new Object()一样
    //通过运行继承创建一个新对象
    function inherit(p) {
        if(p == null) throw TypeError(); //p是一个对象不能为Null
        if(Object.create) return Object.create(p); //如果Object.create存在,则直接使用
        var t = typeof p;
        if(t != 'object' && t != 'function') throw TypeError(); //进一步检测
        function f(){} //空构造函数
        f.prototype = p; //将其原型属性设置为p
        return new f(); //使用f()创建p的继承对象
    }

属性访问错误

如果对象不存在,则试图查询对象的属性就会报错。 null和undefined值都没有属性

    //一种冗余但很易懂的方法
    var len = undefined;
    if(book) {
        if(book.subtitle) len=book.subtitle.length;
    }

    //简练语法
    var len = book && book.subtitle && book.subtitle.length;

删除属性

delete运算符可以删除对象的属性。它的操作数应当是一个属性访问表达式。 但是,delete只是断开属性和宿主对象的联系,而不会操作属性中的属性

delete运算符只能删除自有属性,不能删除继承属性(要删除继承属性,必须从定义这个属性的原型对象删除它,而且会影响到所有继承自这个原型的对象)

检测属性

判断某个属性是否存在于某个对象中,可以通过in运算符、hasOwnPreperty()和propertyIsEnumerable()方法等。

对象的hasOwnProperty()方法:检测给定的名字是否是对象的自有属性,对于继承属性返回false
propertyIsEnumerable():只有检测到是自有属性且这个属性的可枚举性为true是才返回true
in运算符
!==:判断一个属性是否是undefined

var o = {x:0}
o.x !== undefined; //true
o.y !== undefined; //false
o.toString !== undefined; //true

有一种场景只能使用in运算符,而不能使用上述属性访问的方式。 in可以区分不存在的属性和存在但值为undefined的属性

var o = {x:undefined};
o.x !== undefined; //false:属性存在,值为undefined 此时会有问题
o.y !== undefined;
'x' in o; //true:属性存在
'y' in o; //false
delete o.x; //删除x
‘x’ in o; //false
//把p中可枚举的属性赋值到o中,并返回o。 如果有同名属性,则覆盖
function extend(o,p) {
    for(prop in p) {
        o[prop] = p[prop];
    }

    return o;
}

//将p中可枚举的属性复制到o中,并返回o。 如果o和p中有同名属性,o中不受影响
function merge(o,p) {
    for(prop in p) {
        in(o.hasOwnProperty[prop]) continue;
        o[prop] = p[prop];
    }
    return o;
}

//如果o中的属性再p中没有同名属性,则从o中删除这个属性
function restrict(o,p) {
    for(prop in o) {
        if(! (prop in p)) delete o[prop];
    }
    return o;
}

//如果o中的属性在p中存在同名属性,则从o中删除这个属性
function subtract(o, p) {
    for(prop in p) {
        delete o[prop];
    }
    return o;
}

//返回一个新对象,这个对象同时拥有o的属性和p的属性; 如果有重名,则使用p中属性
funciton union(o, p) {
    return extend(extend({}, o), p);
}

//返回一个新对象,同时拥有o和p的属性,像求交集。p中属性的值被忽略
function intersection(o,p) {
    return restrict(extend({}, o), p);
}

属性的特性

  1. 值(value)
  2. 可写性(writable)
  3. 可枚举性(enumerable)
  4. 可配置性(configurable)

通过调用Object.getOwnPropertyDescriptor()可以获得某个对象特定属性的属性描述符

//得到自有属性的描述符
Object.getOwnPropertyDescriptor({x:1}, 'x');
//获得继承属性的特性,需要遍历原型链
Object。getPrototypeOf();
//要想设置属性的特性,或者让新建属性具有某种特性。
Object.definePeoperty(); //传入要修改的对象,要创建或修改的属性的名称以及属性描述符对象

var o = {};
//创建一个不可枚举的数据属性x,赋值为1
Object.defineProperty(o, 'x', {
    value : 1,
    writable:true,
    enumerable:false,
    configurable:true
});

//属性存在不可枚举
o.x;   // 1
Object.keys(o) //[]

//对属性x进行修改,变为只读
Object.defineProperty(o, 'x', {writable:false});

//试图更改这个属性的值
o.x = 2//操作失败但报错,在严格模式里面会抛出类型错误异常
o.x == 1 //true

//配置属性
Object.defineProperty(o, 'x',{value:2});

//强x从数据属性修改为存取器属性
Object.defineProperty(o, 'x', {get:function(){return 0;}});

Object.defineProperty()的属性描述符对象不必包含所有4个特性。
对于新建属性:默认特性值是false或undefined。
对于修改已有属性:默认的特性值没有做任何修改

如果同时修改多个属性,则使用Object.defineProperties();
参数:
1. 要修改的对象
2. 映射表,包含要新建或修改的属性的名称,以及他们的属性描述符

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

原型属性、类属性、可扩展性、序列化对象

原型属性

//ECMAScript5:传递对象,可获取对象的原型
Object.getPrototypeOf()

//ECMAScript3
o.constructor.prototype检测一个对象的原型

类属性

function classof(o) {
    if(o === null) return 'Null';
    if(o === undefined) return 'Undefined';
    return Object.prototype.toString.call(o).slice(8, -1);
}

解析:
      1. object.prototype:object的原型对象,代表继承关系
      2. toString:方法名
      3. call(o):返回数据的类型
      4. 获取里面的值,两个参数截取:包前不包后,负数依然是包前不包后,但是是代表从结尾计数的。

//demo
var p = {x:1};
var o = Object.create(p);
p.isPrototypeOf(o) //true:o继承与p
Object.prototype.isPrototype(o) //true,p继承与Object.prototype

可扩展性

Object.esExtensible(); //判断该对象是否可扩展
Object.preventExtensions(); //对象会变成不可扩展的。 改方法只会影响对象本身的可扩展性。如果给一个不可扩展的对象的原型添加属性,这个不可扩展的对象同样会继承这些新属性
Object.seal()

序列化对象

指:将对象的状态转换为字符串,也可以将字符串还原为对象

JSON.stringify() //序列化
JSON.parse() //还原对象

注意:
1. 支持对象、数组、字符串、无穷大数字、true、false和null
2. NaN、Infinity和-Infinity序列化结果依然是null
3. 日期对象序列化的结果是:ISO格式的日期字符串,但JSON.parse()依然保留他们的字符串形态,而不会还原成日期对象
4. 函数、RegExp、Error对象不支持
5. JSON.stringify() 只能序列化对象可枚举的自有属性,对于一个不能序列化的属性来说,在序列化后的输出字符串会忽略该属性

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章