js对象字面量知识总结

js中创建一个自定义对象有两种方法,一种是使用new,另一种是使用对象字面量形式,至于构造函数模式、工厂模式、原型模式、组合模式、寄生模式、es6中的class、Object.create()等等,都不过是这两种方法的组合应用

在创建一个对象字面量前,要记住几点:

  1. 这种对象不是一个构造函数,不能使用new进行实例化

  2. 它是引用类型,也就意味着对象名是一个指针,当你把对象名赋值给另一个变量时,你在新变量上所做的任何操作都会影响源对象

    var obj={
      id:123
    }
   var b=obj
   b.id=456;
   console.log(obj.id) //456
  1. 对象中的所有成员默认是公开的,如果想实现私有成员,只能采用es6的Symbo来定义一个成员名,然后采用export模块化来达到隔离效果。

一、对象字面量语法

var person={
    name:'小王',
    age:18,
    _pri:233
}

-成员名称的单引号不是必须的
最后一个成员结尾不要用逗号,不然在某些浏览器中会抛出错误
成员名相同会发生什么?
es5普通模式下后定义的会覆盖前面定义的,严格模式则会报错,es6则不管什么模式都采用后面的覆盖前面的

成员名可以是动态变量吗?
es5只能在对象字面量表达式申明以后再添加

var dynamicVar="dyna";
var person={
}
person[dynamicVar]='123';
console.log(person[dynamicVar])

es6则更符合使用场景,可在表达式内创建动态的成员名

var dynamicVar="dyna";
var person={
  [dynamicVar]:'test'
}
console.log(person[dynamicVar])

es6中如果想使用表达式外面的变量名作为成员名,变量的值作为成员值,可进一步简写为

var dynamicVar="dyna";
var person={
  dynamicVar, //这是一个语法糖,js引擎会解释为dynamicVar:'dyna'
  age:15
}
console.log(person.dynamicVar)

注意:此时不能采用person[dynamicVar]方式访问,因为这句话js引擎会解释为person['dyna'],对象中没有dyna属性,肯定就是undefined

可以采用new person()的方式使用吗?
肯定是不可以,new关键字后面必须是一个构造函数才行,对象字面量哪来的构造函数

二、对象成员配置

对象申明后,会默认为内部的每个成员(属性或方法)生成一些隐藏属性,这些隐藏属性是可以读取和可配置的:

Object.getOwnPropertyDescriptor()或getOwnPropertyDescriptor()-读取成员的隐藏属性

Object.definePropertype或Object.defineProperties----设置成员的隐藏属性

相应的隐藏信息如下:

1.configurable

是否可以删除某个成员,默认为true,需要注意的是,如果该属性如果定义为false,后续又定义为true的话会报错

Object.defineProperty(person,'name',{
  configurable:false
})
Object.defineProperty(person,'name',{
 configurable:true
})
2. writable

成员是否可写,默认为true

Object.defineProperty(person,'name',{
  writable:false
})
person.name='小李'; //属性不可写,严格模式下会报错
console.log(person.name); //输出小王,说明上面一句无效
3. enumerable

成员是否可被枚举,默认为rue,该属性主要是用来防范Object.keys()for in的,也就是说该属性设置对于Object.getOwnPropertyNames()方法是无效的。

使用相应的枚举方法,输出的结果是一个数组,那么数组中元素的顺序是按什么规则组织的呢?

在es5中并没有明确这一点,各个浏览器有自己的实现,es6中采用Object.keys()和for in方法时还是没有明确,但采用Object.getOwnPropertyNames()方法枚举时,有了相应的标准:

最先放入数组中的是数值型的成员名,按升序排列;
其次是其它类型的,按添加的先后顺序排列

var obj={

3:'我是1',

1:'我是1',

b:'我是b',

a:'我是a'

}

var names=Object.getOwnPropertyNames(obj);
console.log(names) //["1","3","b","a"]
4. get与set

读写成员时调用的函数,默认为undefined

在文章最开始处的对象定义中,我们创建了一个_pri成员,表示这个成员应在内部读取,下划线只是一个标记符,并不能限制该成员只能在对象内部访问。接下来我们来封装一个属性读写器对_pri成员进行读取,读写器名称随意取,这里叫pri只是为了可读性

Object.defineProperty(person,'pri',{
  get:function(){
    //做一些其它操作
    console.log('准备获取_pri的值')
    return _pri;
  },
  set:function(newValue){
    _pri =newValue
  }
})
person.pri='456';
console.log(person.pri);

如果只有get则表示属性值是只读的,只有set表示只能写。

属性读写器最常用的场景就是在读取或写入属性前可以附带的做一些操作,达到更好的封装性

三、对象保护

禁止添加成员

Object.preventExtensions()该方法用于阻止向对象添加成员,使用Object.isExtensible()`判断对象是否可添加成员

Object.preventExtensions(person);
//添加成员无效,非严格模式下什么都不会发生,严格模式下会报错
person.bankAccount='中国农业银行'
//依然可以删除成员,证明了preventExtensions方法只能阻止添加方法
delete person.age;
console.log(person.age) //undefined,表明删除成功了

禁止添加、删除成员

Object.seal()用来阻止添加或删除成员,判断对象是否是密封的可采用Object.isSealed()

禁止任何操作

使用Object.freeze()方法后,除了不能添加删除成员,连成员的赋值都会失效,但是写入属性(上面set定义的)依然是有效的

四、其它技巧

实现继承

Object.create(person)可产生一个具有继承特性的新对象,但是需要注意的是,父对象的引用类型成员是和子对象共享的,当子对象修改引用类型的成员时,父对象的该成员也会同步发生变化

var person={
  name:'小王',
  age:18,
  _pri:233,
  gf:['豆得儿','张G','TFb']
}
var child=Object.create(person);
child.gf.splice(0,1); //跟豆得儿分手了
console.log(person.gf.length) //父类的gf也变成2了,父子共享女友,尼玛,太乱了

es6中的Object.setPrototypeOf(obj, prototype)方法可将已有的对象变成继承关系,其内部原理也跟Object.create一样,都是将子对象的prototype指向父对象,该方法实现的继承依然有父子对象共享了引用类型成员的问题。

var person={
   age:15
 }
 var man={
     
 }
Object.setPrototypeOf(man,person)
console.log(Object.getPrototypeOf(man)===person) //true
console.log(man.age); //15

重写父对象的成员
直接在子对象中定义一个同名的成员即可

子对象中访问父对象的成员

super关键字是es6新增的,它是一个指针,指向当前对象的原型,也就是父对象

var person={
   age:15,
   testMethod(){
     console.log('我是父类方法')
   }
 }
 var man={
    //重写父类方法
    testMethod(){
      console.log('我是子类方法')
      super.testMethod();
    }
 }
Object.setPrototypeOf(man,person)
man.testMethod();

需要注意的是,如果两个对象不是继承关系,使用super关键字会报错

实现jquery.extend
jquery.extend是一个典行的对象混入,所谓对象混入,就是将n个对象(为了便于表述,直接叫做输入对象)组合成一个新对象,新对象具有各个输入对象的特征,这在软件设计模式中叫做装饰器模式,在es6以前需要自己实现,核心代码如下:

function mixins(target,sourceArr){
  sourceArr.forEach(function(source){
     Object.keys(source).forEach(function(item){
       target[item] = source[item]
     })
  })
  return target
}
var obj1={
  name:'123'
}
var obj2={
  id:100
}
var obj3={
  meth(){
    console.log('haha')
  }
}
var target=mixins(obj1,[obj2,obj3])
target.meth()

上面的代码实现了一个简易版的jquery.extend的浅拷贝模式(也就是deep参数为false时的功能),如果多个对象成员同名,则后面的会覆盖前面的,该代码如果要在正式环境使用,还需要加不少的判断代码,但是在es6中一句话就可以实现mixins()函数的功能。

var target=Object.assign(obj1,obj2,obj3)

需要注意的一点就是输入对象中使用了get修饰符,这时后会有一个转换,方法名变成了新对象的属性名,其值为get修饰符方法中的返回值

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

推荐阅读更多精彩内容