JavaScript对象小结


有关原型链与继承的相关知识,参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

创建对象

  • 对象直接量 【建议使用】
var empty = {};
var point = { x: 0, y: 1} ;
var point2 = { x: point.x, y: point.y };
  • 通过new创建并初始化一个新对象
var o = new Object();
var arr = new Array();
  • 用自定义构造函数来初始化新对象
function range(from, to) {
  this.from = from;
  this.to = to;
}

range.prototype = {
  // ...
}

var r = range(1, 5);
  • Object.create() 【原型继承法】
var o = Object.create(Object.prototype); // 等价于{} 和 new Object()
var o1 = Object.create({x: 1, y: 2});

属性的查询和设置

  • 属性的查询
    有两种方法
var book = { name: 'hhh', author: 'bee' };
var name = book.name;
var author = book['author']; // 注意[]写法,属性名必须加引号,因为其使用字符串值;若为变量,不加。
  • 属性的设置
    同上,有两种方法可以创建属性或给已有属性赋值
book.name = 'hi';
book['main title'] = 'ES5';
  • 属性访问错误
    查询不存在的属性不会报错(返回undefined),但查询一个不存在的对象会报错。null和undefined都没有属性。
book.subtitle; // undefined
book.subtitle.length // TypeError: Cannot read property 'length' of undefined

只有确定book和book.subtitle都是对象,才能直接写book.subtitle.length。

可利用&&运算符的“短路”行为,写出一种简练的方法来避免出错。

var len = book && book.subtitle && book.subtitle.length;

删除属性

delete运算符只能删除自有属性,不能删除继承属性。

已经删除的属性的引用依然存在:

a = {p: {x: 1}};
b = a.p;
delete a.p;

b.x // => 1

因此,在销毁对象时,要遍历属性中的属性,依次删除,避免造成内存泄漏。

delete不能删除那些可配置性为false的属性。某些内置对象的属性是不可配置的,如通过变量声明和函数声明创建的全局对象属性。

delete Object.prototype // false

var x = 1;
delete this.x; // false

function f() {}
delete this.f; // false

删除全局对象的可配置属性时:

this.x = 1;
delete x; // 非严格模式可用
delete this.x; // 严格模式必须加上对全局对象的引用

检测属性

  • in运算符
    检测对象的自有属性继承属性中是否包含这个属性。

in运算符的左侧是属性名(字符串),右侧是对象。

var o = {x: 1}
"x" in o // true
"y" in o // false
"toString" in o // true

此外,可用"!=="判断一个属性是否是undefined:
o.x !== undefined // true
o.y !== undefined // false
o.toString !== undefined // true

但只有in可区分*不存在的属性*和*存在但值为undefined*的属性
  • hasOwnProperty()
    检测给定的名字是否是对象的自有属性。
o.hasOwnProperty("x") // true
o.hasOwnProperty("y") // false
o.hasOwnProperty("toString") // false
  • propertyIsEnumerable()
    检测这个属性是自有属性且是可枚举的。
var o = Object.create({y: 2});
o.x = 1;
o.propertyIsEnumerable("x") // true
o.propertyIsEnumerable("y") // false 【y是继承来的】
Object.prototype.propertyIsEnumerable("toString") // false 【不可枚举】

枚举属性

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

  • Object.keys()
    返回一个由对象中可枚举的自有属性的名称组成的数组。

  • Object.getOwnPropertyNames()
    返回对象的所有自有属性的名称。

var o = {x: 1, y: 2, z: 3};
o.propertyIsEnumerable(x); // true
for (var p in o) { console.log(p); } // x y z

Object.keys(o); // ["x", "y", "z"]

Object.getOwnPropertyNames(Array); // ["length", "name", "arguments", "caller", "prototype", "isArray", "from", "of"]
Object.getOwnPropertyNames(Function); // ["length", "name", "arguments", "caller", "prototype"]

属性getter和setter

详见getter setter

属性的特性

属性包含一个名字和4个特性。4个特性分别是它的值、可写性、可枚举性、可配置性。存取器属性(不具有值特性和可写性,可写性由setter方法存在与否决定)的4个特性是读取、写入、可枚举性、可配置性。

ES5定义了一个名为“属性描述符”(property descriptor)的对象,代表那4个特性。

  • Object.getOwnPropertyDescriptor()
    获得某个对象特定属性的属性描述符。
Object.getOwnPropertyDescriptor({x: 1}, "x") 
// {value: 1, writable: true, enumerable: true, configurable: true}

var random = {
  get octet() { return Math.floor(Math.random() * 256); }
}
Object.getOwnPropertyDescriptor(random, "octet") 
// {set: undefined, enumerable: true, configurable: true, get: ƒ}

要想获得继承属性的特性,需要遍历原型链,参照Object.getPrototypeOf()

  • Object.defineProperty()
    设置属性的特性。
var obj = {key: 'temp'};
Object.getOwnPropertyDescriptor(obj, "key");
// {value: "temp", writable: true, enumerable: true, configurable: true}

Object.defineProperty(obj, "key", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: "static"
}); // {key: "static"}
Object.getOwnPropertyDescriptor(obj, "key");
// {value: "static", writable: false, enumerable: false, configurable: false}

对象的三个属性

只有一种间接的方法可以查询:默认的toString()方法(继承自Object.prototype)。为了调用正确的(而不是被重写的)toString()版本,必须间接调用Function.call()方法。

var o = [1, 2];
Object.prototype.toString.call(o).slice(8, -1); // 'Array'

序列化对象

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

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

对象方法

  • toString()
  • toLocaleString()
  • toJSON()
  • valueOf()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容