对象的概念

/*这段时间面试,被问到一些对象原理就答不上来,感觉自己对于一些知识点的理解不够系统,在这里对一些知识点做统一的整理,有不对的地方也欢迎大家提出来(#.#)
文章中有借鉴其他文章中的内容,若有侵权,联系必删 q:1097925740 */

什么是对象?

ECMA-262(ECMAScript5.1的规范)规定:对象是一组属性的无需集合,每个属性和方法都有一个名称来标识,这个名称映射到这个值。

对象属性

对象中的属性决定了对象的特征,对象特征决定了对象在js中的行为。
ECMA-262使用了一些内部特性来描述属性特征。开发者不能在js中直接访问这些属性。
内部特性表示:[[enumerable]]
属性分为两种:数据属性、访问器属性。

数据属性

数据属性包含一个保存数据值的位置([[value]]),值会从这个位置被读取、也会被写入到这个位置。

数据属性的四个特性:
  1. [[configurable]] 表示属性是否可以被删除、重新定义、修改特性、改为访问器属性,直接定义在对象上的属性默认true;一个属性[[configurable]]特性被设置为false后,不可再修改为true。
  2. [[enumerable]] 是否可以被for…in遍历,直接定义在对象上的属性默认true;
  3. [[writable]] 属性值是否可以被修改,直接定义在对象上的属性默认true;
  4. [[value]] 指属性的实际值,前面提到的读入和写入的位置,默认undefined

修改属性的默认特性: object.defineProperty;
实现:object.defineProperty(对象,对象属性名,{ 描述符对象})

访问器属性

访问器属性不包含数据值,包含一个获取函数(getter)和设置函数(setter)

访问属性的四个特性:
  1. [[configurable]] 是否能够删除并重新定义,修改特性,修改它为数据属性;直接定义在对象上的属性默认true;
  2. [[enumerable]] 是否可以遍历,直接定义在对象上的属性默认true;
  3. ** [[get]] ** 用于获取函数,在读取函数时调用,默认为undefined
  4. ** [[set]] ** 设置函数,写入函数时调用,默认值为undefined

访问器属性的定义: object.defineProperty;
实现:object.defineProperty(对象,对象属性名,{ 描述符对象})
通过object.defineProperty定义私有成员(一般加_的表示私有)和公共成员。
拓展:私有成员的定义。

object.property(book,'year',{
get(){
return this.year_;   //此处通过访问year去return year_,让用户真正访问的不是真实year_,避免用户修改year_,使year_私有。
}
set(value){
this.year_ = value;    //设置year_值。
}
})

定义多个属性

object.properties()方法可以实现一次性定义多个属性。
object.properties(对象,{描述符对象}),其属性要与添加修改的属性意义对应。
通过object.defineProperty定义的属性特性值默认为false;

读取属性特性

Object.getPropertyDescriptor(对象,对象属性名).[[特性]]

合并对象

把源对象属性复制到目标对象上。
object.assign(目标对象,源对象)将源对象的可遍历属性通过get\ser方法复制到目标对象上,最后返回修改后的目标对象。
object.assign是一个浅复制:

  1. 如果多个源对象有相同的属性,最后一个对象的属性会覆盖前面的属性。
  2. 不能在两个对象中转移函数和设置函数。
  3. 属性为对象时,复制的是对象的引用。
  4. 遇到error停止复制,只能复制error之前的。

对象解构

解构:可以在一个类似对象字面量的结构中,声明多个变量,同时执行多个赋值操作。
对象结构匹配规则:属性名的匹配,引用属性在源对象中不存在,启用默认值undefined。
解构不要求变量必须在结构表达式中声明,但是先声明的变量,应该用小括号将赋值表达式括起来。
如:({name:‘w’,age:‘22’} = person) //name、age是已经定义的变量

嵌套解构

let {job:{title}} = person; //外层属性没有定义的情况下不能使用嵌套解构 。
普通解构也能完成对对象的复制,但是复制了对象引用,改变源对象目标对象也发生改变,属于浅拷贝。嵌套解构可实现深拷贝。

部分解构

解构表达式涉及到多个赋值,开始的赋值成功,后面的赋值失败,即完成部分解构

参数上下文匹配

函数参数中也可使用解构赋值,argument不会受影响。

function printPerson(a,{name,age},c){}   //声明
 printPerson(1,person,3)   //调用,在参数中进行解构赋值,person是一个对象

创建对象

创建对象的方法:
  • Object构造函数
var p = new Object()
p = {}
p.name = '丁七岁'
p.age = 19
p.setName = function (name) {
    this.name = name
}
p.setaAge = function (age) {
    this.age = age
}
console.log(p)
  • 对象字面量
  var p = {
    name: '木柠QAQ',
    age: 19,
    setName: function (name) {
      this.name = name
    }
  }
  console.log(p)
  p.setName('柠木QAQ')
  console.log(p)

  var p2 = {
    name: '丁七岁',
    age: 19,
    setName: function (name) {
      this.name = name
    }
  }
  console.log(p2)

以上创建方式的缺点:创建具有同样接口的多个对象,需要写很对的重复代码。

  • 工厂模式
  function createPerson(name, age) {
    var p = {
      name: name,
      age: age,
      setName: function (name) {
        this.name = name
      }
    }
    return p
  }

  var p1 = createPerson('ding', 19)
  var p2 = createPerson('QiSui', 18)
  console.log(p1)
  console.log(p2)

该方法解决了代码重复问题,但是没有解决对象标识的问题(新创建的对象是什么类型)

  • 构造函数模式
  function Person(name, age) {
    this.name = name
    this.age = age
    this.setName = function (name) {
      this.name = name
    }
  }

  var p1 = new Person('丁七岁', 18)
  var p2 = new Person('丁七岁2', 19)
  console.log(p1, p1 instanceof Person)
  console.log(p1, p2 instanceof Person)

Person()构造函数代替了createPerson()工厂函数,两个函数的内部代码基本一样,只是有以下区别:

  1. 没有显式得创建对象
  2. 属性和方法直接赋值给this
  3. 没有return
    按照语法习惯,构造函数首字母应该大写。
    创建Person实例应该使用new操作符,具体的操作流程:
function newFun(construct,name){
        let obj = {};
        obj.__proto__ = construct.prototype;
        construct.call(obj,name);
        return obj;
    }

构造函数也是函数:区别普通函数在于他们调用方式不同。
构造函数的问题:
构造函数上定义的方法在每个实例上都创建一遍
解决:
把函数定义到构造函数外部,属性的值是方法的引用地址,不会对方法进行调用。

  function Person(name, age) {
    this.name = name
    this.age = age
    this.setName = setName
  }
  function setName(name) {
      this.name = name
  }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值