1. JavaScript Object

此文章用于归纳Object的所有方法


在JavaScript中,object是所有对象的基础(原型链的顶端),所以,他具有的这些方法、属性,也是所有对象都具有的方法、属性,可能具体到方法会有所不同(因为原型覆盖,重写),但是属性名都相同,内容也有相似的地方。

object的每个实例都具有下列属性和方法(Object .prototype里的方法):

  • constructor:构造函数,保存着用于创建当前对象的函数。例子如下:
var obj = new Object();
console.log(obj.constructor);//function Object() { [native code] }

[native code]是什么呢?我大概的把它理解为由JS引擎自己内部实现的代码,而非JS代码。

  • hasOwnProperty('propertyName'):该方法接受一个参数(传入的参数必须是以字符串的形式),用于检查传入的属性名对应的属性是否是当前对象自己拥有的(而非通过原型链继承过来的)。如果是,返回true,不是,返回false。例子如下:
var obj = new Object();
console.log(obj.hasOwnProperty('toString'));//false
obj.toString = function(){return 123};
console.log(obj.hasOwnProperty('toString'));//true
  • isPrototypeOf(obj):该方法接受一个参数,用于检查传入的对象的原型链是否包含当前对象。例子如下:
function Foo() {}
function Bar() {}
function Baz() {}
Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);
var baz = new Baz();
console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true

特别注意,不要和instanceof弄混淆了。

A.isPrototypeOf(B) //判断的是A对象是否存在于B对象的原型链之中
A instanceof B  //判断的是B.prototype是否存在与A的原型链之中
  • propertyIsEnumerable('propertyName'):接受一个参数,与hasOwnProperty('propertyName')类似,只能传入字符串参数,其作用是用来检查传入参数对应的属性是否是可枚举的,如果可枚举返回true,就可以用for in循环,反之不行,返回false。其代码是:
var obj = {};
Object.defineProperty(obj, 'prop1', {
  enumerable: false,
});
Object.defineProperty(obj, 'prop2', {
  enumerable: true,
});
console.log(obj.propertyIsEnumerable('prop1'));//false
console.log(obj.propertyIsEnumerable('prop2'));//true
  • toLocaleString():返回对象的字符串表示,该字符串与区域设置有关。其返回值是表示对象的字符串。用的最多的是被其覆盖的Date.prototype.toLocaleString()。具体代码如下:
var obj = {a:'1123aa'};
obj.toLocaleString();//"[object Object]"
  • toString():返回对象的字符串表示,其返回值是表示对象的字符串。具体代码如下:
var obj = {a:'1123aa'};
obj.toString();//"[object Object]"

可以通过Object.prototype.toString去检测一个内置对象是属于什么类型。需要用到call或者apply,具体代码如下:

var toString = Object.prototype.toString;
toString.call(new Date);    // [object Date]
toString.call(new String);  // [object String]
toString.call(Math);        // [object Math]
toString.call(undefined);   // [object Undefined]
toString.call(null);        // [object Null]

值得注意的是,一定是内置对象,如果是其他对象,统一返回[object object ].

  • valueOf():返回对象的原始值。具体代码如下:
var obj = {a:'1123aa'};
obj.valueOf();//Object {a: "1123aa"}

值得注意的是数据类型在做转换的时候,一般是先用valueOf()转换,再用toString()进行转换。但是如果是Date类型的数据,是先用toString(),再用valueOf()



object自身的方法:

  • Object.assign(target,····source):该方法是ES6的方法,接受2‘个’参数,第一个参数是目标对象,第二个参数是多个参数,以逗号形式连接的‘源对象’。该方法是用于将所有可以枚举的属性的值从一个或者多个源对象复制到目标对象,并返回目标对象。
    关于 Object.assign(),还有几点值得注意:
  1. 如果目标对象与源对象都有相同的属性,以源对象为准。如果源对象之间,有相同的属性,以源对象排在后面的为准。
  2. 如果在复制过程中,抛出错误,目标对象保持不变 。
  3. Object.assign()只复制自身的属性,不可枚举的属性(enumerablefalse)和继承的属性不会被复制。
  4. Symbol也会被复制。
  5. 如果复制的属性本身是对象,那么进行浅拷贝,如果已有该属性,会被替换。
  6. 如果复制的属性本身是数组,那么会被视为属性名为0、1、2的对象来处理,具体如下:
Object.assign([1,2,3],[4,5])//[4, 5, 3]
  1. 只要参数中,有一个不是对象,就会报TypeError错误。
    其具体代码如下:
let obj1 = { a: 0 , b: { c: 0}};
  let obj2 = Object.assign({}, obj1);
  console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
  obj1.a = 1;
  console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
  console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
   obj2.a = 2;
  console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
  console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
  obj2.b.c = 3;
  console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
  console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}
  //深拷贝
  obj1 = { a: 0 , b: { c: 0}};
  let obj3 = JSON.parse(JSON.stringify(obj1));
  obj1.a = 4;
  obj1.b.c = 4;
  console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
  • Object.create(prototype,descriptors):该方法一共有2个参数,第一个参数为必选,是要用作原型的对象。可以为null,如果是null,会创建一个没有继承任何方法的对象,这个对象可以当做伪全局变量,存一些东西。第二个参数可选,包含一个或多个类似于Object.defineProperty()函数的对象。
    Object.create(prototype,descriptors)具体用法太多,太杂,这里就不做深入了,也很难深入下去了,单独第一个参数还好,用于继承什么的。第二个参数就很复杂了,我觉得应该和开发底层框架有关吧,也许。关于Object.create(prototype,descriptors)只包含第一个参数的例子,可以去我之前写过的《JavaScript 继承!我有话要说》看看。

  • Object.defineProperty(obj, prop, descriptor):该方法用于给对象上定义一个新属性,或者修改该对象上的现有属性,并返回该对象。此方法一共有3个参数,第一个参数期待一个对象,之后的操作都是基于这个对象的。第二个参数是需要定义或者修改的属性名。第三个参数是定义或者修改属性的描述符(descriptor)。
    这个方法和一般直接定义属性有些不一样,或者说更加严格,规范一些。用在底层框架比较多。描述符里面有configurableenumerable等等限定该属性功能,行为,值的属性描述符和数据描述符。如下代码:
var obj = {a : 2};
Object.getOwnPropertyDescriptor(obj,'a')//Object {value: 2, writable: true, enumerable: true, configurable: true}

可以看到,obja属性有4个描述符,其中一个是value,是数据描述符。还有另外3个是,configurable(可配置),enumerable(可枚举),writable(可写)。下面,我们来详细讲解一下这3个描述符。

  1. writable:决定了是否可以修改属性的值。具体代码如下:
var obj = {};
Object.defineProperty(obj,'a',{
value:2,
writable:false,//不可修改!
configurable:true,
enumerable:true,
})
obj.a = 3;//尝试修改
console.log(obj.a)//2

正如你所看到的,我们赋值3失败了,因为这个属性被定为writable:fasle不可写。如果在严格模式下,这样值,会报错TypeError
其实在我们定下writable:fasle的时候,已经设定了一个空操作setter,所以,要和writable:fasle一致,需要将setter调用时,抛出一个TypeError错误。

  1. configurable:如果该属性是 configurable:true,就可以使用Object.defineProperty(··)来修改描述符,代码如下:
var obj = {};
Object.defineProperty(obj,'a',{
value:2,
writable:true,
configurable:false,//不可配置!
enumerable:true,
})
obj.a = 3;
console.log(obj.a)//3
//尝试配置obj
Object.defineProperty(obj,'a',{
value:2,
writable:true,
configurable:true,
enumerable:true,
})//TypeError!

所以可以看出configurable:false是单向的,不可逆的。还有两点,第一点,就算是configurable:false,我们还可以修改writable:truefalse,但是不能将false变为true。第二点,当configurable:false时,此时的a属性是无法delete的。

  1. enumerable:决定了该属性是否可枚举。没什么说的,设置为falsefor in循环无法遍历这个属性。
  • Object.defineProperties(obj, props):和Object.defineProperty(obj, prop, descriptor)功能类似,只不过可以同时定义多个属性,具体如下:
var obj = {};
Object.defineProperties(obj, {
  'a': {
    value: true,
    writable: true
  },
  'b': {
    value: 'Hello',
    writable: false
  }
  });
obj.a//true
  • Object.freeze(obj):该方法是用来冻结一个对象,也就是阻止添加新属性; 防止现有属性被删除; 并防止现有属性或其可枚举性,可配置性或可写性更改。该方法返回冻结状态下的对象。该方法期待一个为对象的参数。
    其实这个方法相当于对当前对象调用Object.seal()并且将所有的'数据访问'属性标记为writable:false
  • Object.seal(obj):该方法创建一个密封的对象,实际上是对该对象调用Object.preventExtensions(··)并把所有现有属性标记为configurable:false
  • Object.preventExtensions(obj):如果你想禁止一个对象添加新属性并且保留自己的已有属性,就可以使用该方法。
var obj = {a:2};
Object.preventExtensions(obj);
obj.b = 3;
obj.b//undefined
  • Object.getOwnPropertyDescriptor(obj, prop):该方法接受2个参数,第一个参数是被查找属性的对象,第二个对象是查找的属性名,如果存在该属性,返回其属性描述符,如果不存在,返回undefined
  • Object.getOwnPropertyNames(obj):该方法返回一个给定对象的所有属性名(可枚举或不可列)的数组。代码如下:
var obj = { 0: 'a', 1: 'b', 2: 'c' };
Object.getOwnPropertyNames(obj);//["0", "1", "2"]
  • Object.getOwnPropertySymbols(obj):该方法返回一个给定对象的所有符号属性名的数组。代码如下:
var obj = {};
var a = Symbol('a');
var b = Symbol('b');
obj[a] = 'aaa';
obj[b] = 'bbb';
Object.getOwnPropertySymbols(obj);//[Symbol(a), Symbol(b)]
  • Object.getPrototypeOf(obj):该方法返回指定对象的原型prototype。具体代码如下:
var str = '123';
Object.getPrototypeOf(str)//String.prototype
  • Object.is(value1,value2)该方法接受2个参数,比较2个参数是否相等。与===有一点不同,具体如下:
console.log(-0 === +0)//true
console.log(Object.is(-0,+0))//false

Object.is(value1,value2)是要真的等,才返回true。

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

推荐阅读更多精彩内容

  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,718评论 2 17
  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 2,056评论 1 10
  • JS基础讲解 JavaScript组成ECMAScript:解释器、翻译DOM:Document Object M...
    FConfidence阅读 570评论 0 1
  • 来自:参 考 原 文 对象是由多个名/值对组成的无序的集...
    wyude阅读 1,240评论 1 7
  • 莫要怪我太过优柔 多年后才与你相识 实际上我等的不是你 只是见你第一面时蹿动的心鸾 在这白雪飘舞的时节出现 过去我...
    碧波飞龙阅读 97评论 0 0