再次理解javaScript的对象(Object)

简言

再次回顾理解JavaScript中的对象概念。

js对象

对象概念

对象是一个包含相关数据和方法的集合(通常由一些变量和函数组成,我们称之为对象里面的属性和方法)。对象包含三个要素:

  • 唯一标识: 这个对象的标记,通过它可以找到和理解这个对象;js是靠内存地址表示对象的唯一标识。
  • 状态: 对象的各种描述性属性。
  • 行为:对象的行为。

创建js对象

js对象创建有多种方式:

  • {} 、new
  • Object.create()

我们先来看使用上面三种创建的对象示例:

 //  1. {}
    const a = {}
    console.log(a);

    //  2. new 
    const b = new Object()
    console.log(b);
    const c = new function () {

    }
    console.log(c);

    //  3. Object.create()
    const d = Object.create(null)
    console.log(d);

结果都是一个空对象,只是他们的原型对象里的构造函数不同在这里插入图片描述
那是因为a和b是基于Object创建的,c基于Function,d基于null。
它们都可以添加自己的属性(property),属性是用键值对(key/value)来描述的,key可以是字符串、number和Symbol类型,value则可以是任意类型。

    const a = {
      name: 'zsk6',
      'a': 123,
      6: {
        name: 'lala',
        age: 18
      },
      fn: () => {
        console.log('我是fn');
      }
    }

使用js对象

使用对象一般就是调用里面的属性,有以下两种方式:

  • 点(.)操作符
  • 中括号[]操作符
    示例:
    在这里插入图片描述
    另外,你可以添加或修改属性,自身的普通属性通过上面的方式可以修改和添加(不存在就是添加,存在就修改)。

原型链

每个对象都有一个原型对象,属于不可以的内置对象,用[[Prototype]]表示,js的对象创建不可能凭空出现,他需要基于其他对象来创建,类似面向对象的继承,但它不是复制其他对象的属性,而是使用原型对象来和其他对象建立联系,你可以使用浏览器提供的__proto__和官方提供的Object.getPrototypeOf()来访问对象的[[Prototype]]。

   const a = {
      name: 'zsk6',
      'a': 123,
      6: {
        name: 'lala',
        age: 18
      },
      fn: () => {
        console.log('我是fn');
      }
    }


    const aa = Object.create(a)
    aa.name = 'aa'
    console.log(aa.__proto__, Object.getPrototypeOf(aa));

原型链 ----当你创建的对象继承层级足够多的时候,访问本身不存在的属性时,js会依靠[[Prototype]]来尝试读取原型上是否有改属性,若没用继续依靠原型的[[Prototype]]尝试读取是否有改属性,直至找到顶层null,若找不到则认为是未定义(undefined),这种链式查找方式称为原型链。
如果是对象有构造函数,那么构造函数会有一个prototype属性可以访问[[Prototype]]。

 const A = function (name, age) {
      this.name = name
      this.age = age
    }
    const AA = new A('zsk', 18, 22)
    //  AA实例对象 A构造函数
    console.log('AA实例对象 A构造函数', AA, A);
    //  AA.__proto__ 指向原型对象  A.prototype也只原型对象 ,AA 和 A 是不同的观察角度,就像两个人打游戏,我抢A包点,你守A包点,最终都会去A包点,
    console.log(AA.__proto__, A.prototype, A.prototype === AA.__proto__);
    //  AA.__proto__.__proto__ 指向A的原型对象(Object) ,
    console.log(AA.__proto__.__proto__, A.prototype.__proto__, Object.prototype, Object.__proto__.__proto__);
    //  顶层对象null
    console.log(AA.__proto__.__proto__.__proto__, A.prototype.__proto__.__proto__, Object.prototype.__proto__, Object.__proto__.__proto__.__proto__);

    //  我们给A原型添加属性,
    A.prototype.hh = '嘿嘿'
    console.log('我们给A原型添加属性,', AA.hh);
    //  我们给Object原型添加属性aa
    Object.prototype.aa = '哈哈'
    console.log('我们给Object原型添加属性aa', AA.aa);

效果:
在这里插入图片描述
查找路径:
AA---->AA.proto(构造函数A)---->Object---->null
找得到就调用,找不到undefined。

内置对象Object

万物皆对象。js内置了很多的特殊对象。例如Object、Array、Math、Function、Date、Number、String等等。
这里只了解Object。
Object 是 JavaScript 的一种 数据类型 。它用于存储各种键值集合和更复杂的实体。Objects 可以通过 Object() 构造函数或者使用 对象字面量 的方式创建。

Object的属性

上文我们知道对象是用属性来定义行为和状态的。
官方使用描述符对象来描述属性,对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。
描述符键值描述:

键值描述
configurable当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false。configurable 特性表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改。
enumerable当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false。定义了对象的属性是否可以在 for…in 循环和 Object.keys() 中被枚举。
value该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined
writable当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符 (en-US)改变。 默认为 false。
get属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 默认为 undefined。
set属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 undefined。

描述符可拥有的键值:

configurableenumerablevaluewritablegetset
数据描述符
存取描述符
  • 拥有布尔值的键 configurable、enumerable 和 writable 的默认值都是 false。
  • 属性值和函数的键 value、get 和 set 字段的默认值为 undefined。

如果一个描述符不具有 value、writable、get 和 set 中的任意一个键,那么它将被认为是一个数据描述符。如果一个描述符同时拥有 value 或 writable 和 get 或 set 键,则会产生一个异常。
示例:

    const obj = {};
    //  定义描述符 , Object.create()原型指向null,意思是不受其他影响,纯净的{}
    const descriptor = Object.create(null); // 没有继承的属性
    // 默认没有 enumerable,没有 configurable,没有 writable
    descriptor.value = 'static';
    descriptor.configurable = true  //  描述符对象可变
    Object.defineProperty(obj, 'key', descriptor);

    // 显式
    Object.defineProperty(obj, "key", {
      enumerable: true, //  可遍历
      configurable: true, //  
      writable: false,
      value: "static"
    });
    obj.key = '123'
    console.log(obj.key);
    //  报错,Cannot redefine property: key 不能重新定义key值
    Object.defineProperty(obj, "key", {
      enumerable: true,
      configurable: false,
      writable: false,
      value: "static2", // 重新设描述符值
    });

    //  没屁用,writable为false,不可写
    obj.key = 'zsk'
    console.log(obj.key);

如果对象中不存在指定的属性,Object.defineProperty() 会创建这个属性。当描述符中省略某些字段时,这些字段将使用它们的默认值。
get和set使用

function Archiver() {
  var temperature = null;
  var archive = [];

  Object.defineProperty(this, 'temperature', {
    get: function() {
      console.log('get!');
      return temperature;
    },
    set: function(value) {
      temperature = value;
      archive.push({ val: temperature });
    }
  });

  this.getArchive = function() { return archive; };
}

var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]

当访问者的属性是被继承的,get和set存储访问的值需要使用this,才不会被实例对象共享

function myclass() {
}

Object.defineProperty(myclass.prototype, "x", {
  get() {
    return this.stored_x;
  },
  set(x) {
    this.stored_x = x;
  }
});

var a = new myclass();
var b = new myclass();
a.x = 1;
console.log(b.x); // undefined

结语

结束了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZSK6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值