Object 对象

JavaScript 原生提供 Object 对象

JavaScript 的所有其他对象都继承自  Object 对象,即那些对象都是Object的实例

  • Object 对象的原生方法分成两类:

    • Object 对象本身的方法

      • 就是直接定义在 Object 对象的方法
      • 对象自身的方法(又称为”静态方法“)和实例方法两部分
    • Object 的实例方法
      • 定义在 Objec 原型对象 Object.prototype 上的方法,可以被 Object 实例直接使用
  • Object() 本身是一个函数

    • 将任意值转为对象。这个方法常用于保证某个值一定是对象

      • var obj = Object();
        
        // 等同于
        var obj = Object(undefined);
        var obj = Object(null); obj instanceof Object // true
    • instanceof运算符用来验证,一个对象是否为指定的构造函数的实例
    • obj instanceof Object 返回 true,就表示 obj 对象是 Object 的实例
    • Object (原始类型的值)    Object 方法将其转为对应的包装对象的实例
    • Object (一个对象)    总是返回该对象,即不用转换
      • // 判断变量是否为对象的函数
        function isObject(value) {
        return value === Object(value);
        } isObject([]) // true
        isObject(true) // false
  • new Object()构造函数    的首要用途是 :  直接通过它来生成新对象。
    • // 通过var obj = new Object()的写法生成新对象,
      // 与字面量的写法var obj = {}是等价的。
      // 或者说,后者只是前者的一种简便写法
      // Object(value)与new Object(value)两者的语义是不同的
      // Object(value)表示将value转成一个对象
      // new Object(value)则表示新生成一个对象,它的值是value
  • Object.keys() 接受一个对象作为参数,返回一个数组,该数组的成员都是该对象自身的(而不是继承的)所有属性名
  • Object.getOwnPropertyNames()   接受一个对象作为参数,返回一个数组,包含了该对象自身的所有属性名
    • Object.keys()方法    只返回可枚举的属性(详见《对象属性的描述对象》一章)
    • Object.getOwnPropertyNames()方法    还返回不可枚举的属性名
    • var a = ['Hello', 'World'];
      
      Object.keys(a)     // ["0", "1"]
      Object.getOwnPropertyNames(a) // ["0", "1", "length"] // 数组的length属性是不可枚举的属性,所以只出现在Object.getOwnPropertyNames() 方法的返回结果
    • 自定义计算对象属性个数的方法
      var obj = {
      p1: 123,
      p2: 456
      }; Object.keys(obj).length; //
      Object.getOwnPropertyNames(obj).length; //
  • 其他静态方法
    • 对象属性模型的相关方法

      • Object.getOwnPropertyDescriptor():    获取某个属性的描述对象。
      • Object.defineProperty():    通过描述对象,定义某个属性。
      • Object.defineProperties():    通过描述对象,定义多个属性。
    • 控制对象状态的方法
      • Object.preventExtensions():    防止对象扩展。
      • Object.isExtensible():    判断对象是否可扩展。
      • Object.seal():    禁止对象配置。
      • Object.isSealed():    判断一个对象是否可配置。
      • Object.freeze():    冻结一个对象。
      • Object.isFrozen():    判断一个对象是否被冻结。
    • 原型链相关方法
      • Object.create():    该方法可以指定原型对象和属性,返回一个新的对象。
      • Object.getPrototypeOf():    获取对象的Prototype对象。
  • 定义在 Object.prototype 对象的 实例方法        所有Object的实例对象都继承了这些方法。

    • Object.prototype.valueOf()    返回当前对象对应的值。

      • 返回一个对象的“值”,默认情况下返回对象本身

        • var obj = new Object();
          obj.valueOf() === obj; // true
      • 自动类型转换时会默认调用这个方法
      • 如果自定义valueOf方法,就可以得到想要的结果
        • var obj = new Object();
          obj.valueOf = function () {
          return 2;
          }; 1 + obj // 3 // 用自定义的obj.valueOf,覆盖Object.prototype.valueOf
    • Object.prototype.toString()    返回当前对象对应的字符串形式。
      • 返回一个对象的字符串形式,默认情况下返回类型字符串

        • var o1 = new Object();
          o1.toString() // "[object Object]" var o2 = {a:1};
          o2.toString() // "[object Object]" 该字符串说明对象的类型。
      • 通过自定义toString方法,可以让对象在自动类型转换时,得到想要的字符串形式。
        • var obj = new Object();
          
          obj.toString = function () {
          return 'hello';
          }; obj + ' ' + 'world' // "hello world"
      • 数组、字符串、函数、Date 对象调用toString方法,并不会返回[object Object],因为它们都自定义了toString方法,覆盖原始方法
        • [1, 2, 3].toString()    // "1,2,3"
          
          '123'.toString()    // "123"
          
          (function () {
          return 123;
          }).toString();
          // "function () {
          // return 123;
          // }" (new Date()).toString(); // "Tue May 10 2016 09:11:31 GMT+0800 (C
      • 直接使用Object.prototype.toString方法。通过函数的call方法,可以在任意值上调用这个方法,帮助我们判断这个值的类型
        • Object.prototype.toString.call(value);
      • 自定义一个比typeof运算符更准确的类型判断函数
        • var type = function (o){
          var s = Object.prototype.toString.call(o);
          return s.match(/\[object (.*?)\]/)[1].toLowerCase();
          }; type({}); // "object"
          type([]); // "array"
          type(5); // "number"
          type(null); // "null"
          type(); // "undefined"
          type(/abcd/); // "regex"
          type(new Date()); // "date" // 在上面这个type函数的基础上,还可以加上专门判断某种类型数据的方法
          ['Null',
          'Undefined',
          'Object',
          'Array',
          'String',
          'Number',
          'Boolean',
          'Function',
          'RegExp'
          ].forEach(function (t) {
          type['is' + t] = function (o) {
          return type(o) === t.toLowerCase();
          };
          }); type.isObject({}) // true
          type.isNumber(NaN) // true
          type.isRegExp(/abc/) // true
    • Object.prototype.toLocaleString()    返回当前对象对应的本地字符串形式。
      • 与toString的返回结果相同,也是返回一个值的字符串形式
      • 主要作用是留出一个接口,让各种不同的对象实现自己版本的toLocaleString,用来返回针对某些地域的特定的值
      • 目前,主要有三个对象自定义了toLocaleString方法
        • Array.prototype.toLocaleString()
        • Number.prototype.toLocaleString()
        • Date.prototype.toLocaleString()   
          • // 日期 Date 的实例对象的toString和toLocaleString返回值就不一样,而且toLocaleString的返回值跟用户设定的所在地域相关
    • Object.prototype.hasOwnProperty()    判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。
    • Object.prototype.isPrototypeOf()    判断当前对象是否为另一个对象的原型。
    • Object.prototype.propertyIsEnumerable()    判断某个属性是否可枚举。

属性描述对象 attributes object

JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等

  • {
    value: undefined, // 该属性的属性值,默认为undefined writable: true, // 表示属性值(value)是否可改变(即是否可写),默认为true enumerable: true, // 表示该属性是否可遍历,默认为true。如果设为false,会使得某些操作(比如for...in遍历对象和对象原型中可以遍历的属性、Object.keys())跳过该属性 configurable: true, // 表示可配置性,默认为true。如果设为false,将阻止某些操作改写该属性,
    // 比如无法删除该属性,也不得改变该属性的属性描述对象(value属性除外)。也就是说,configurable属性控制了属性描述对象的可写性。 get: undefined, // 表示该属性的取值函数(getter),默认为undefined 每次读取该属性,都会调用这个取值函数
    // 一旦定义了取值函数get(或存值函数set),就不能将writable属性设为true set: undefined // 表示该属性的存值函数(setter),默认为undefined
    } // 方式1
    var obj = Object.defineProperties({}, {
    p1: { value: 1, enumerable: true },
    p2: { value: 2, enumerable: false }
    }); // 方式2
    var obj = {name:"Tom", age:"22"};
    Object.defineProperty(obj, "name", {
    writable: false, // 属性不可写
    enumerable: false, // 属性不可遍历 如 for in 将跳过 name 属性
    configurable: false, // 属性不可配置 如 delete name
    }); Object.defineProperty(obj, 'fullName', {
    get:function(){
    return this.name + "Michal";
    },
    set:function(newName){
    this.name = newName.split(" ")[0];
    }
    });
  • Object.getOwnPropertyDescriptor() 方法
    • 获取对象某个属性的属性描述对象
    • 第一个参数是目标对象。
    • 第二个参数是一个字符串,对应目标对象的某个属性名。
    • 只能用于对象自身的属性,不能用于继承的属性。。。对于继承的属性,返回 undefined
      • var obj = { p: 'a' };
        
        // 获取obj.p的属性描述对象
        Object.getOwnPropertyDescriptor(obj, 'p'); // Object {
        // value: "a",
        // writable: true,
        // enumerable: true,
        // configurable: true
        // }
  • Object.getOwnPropertyNames() 方法
    • 返回一个数组,成员是参数对象自身的全部属性的属性名,不管该属性是否可遍历
  • Object.defineProperty(object, propertyName, attributesObject) 方法

    • 通过属性描述对象,定义或修改一个属性,然后返回修改后的对象
    • object    属性所在的对象
    • propertyName    字符串,表示属性名
    • attributesObject    属性描述对象
      • var obj = Object.defineProperty({}, 'p', {
        value: 123,
        writable: false, // 不可写
        enumerable: true,
        configurable: false
        }); obj.p // obj.p = 246;
        obj.p //
  • Object.defineProperties()
    • var obj = Object.defineProperties({}, {
      p1: { value: 123, enumerable: true },
      p2: { value: 'abc', enumerable: true },
      p3: { get: function () { return this.p1 + this.p2 }, // 每次读取该属性,都会调用这个取值函数
      enumerable:true,
      configurable:true
      }
      }); obj.p1 //
      obj.p2 // "abc"
      obj.p3 // "123abc"
  • Object.prototype.propertyIsEnumerable()
    • 用于判断某个属性是否可遍历
    • 只能用于判断对象自身的属性,对于继承的属性一律返回false
      • var obj = {};
        obj.p = 123; obj.propertyIsEnumerable('p'); // true
        obj.propertyIsEnumerable('toString'); // false

元属性

指属性描述对象的各个属性,即控制属性的属性

  • value 属性是目标属性的值

    • var obj = {};
      obj.p = 123; Object.getOwnPropertyDescriptor(obj, 'p').value; // Object.defineProperty(obj, 'p', { value: 246 }); obj.p //
  • writable 属性,决定了目标属性的值(value)是否可以被改变
    • 正常模式下,对writable为false的属性赋值不会报错,只会默默失败
    • 但是,严格模式下会报错,即使对 a 属性重新赋予一个同样的值
    • 'use strict';    // 采用严格模式
      
      var obj = {};
      
      Object.defineProperty(obj, 'a', {
      value: 37,
      writable: false
      }); obj.a = 37; // Uncaught TypeError: Cannot assign to read only property 'a' of object
    • __proto__是原型对象,它的foo属性不可写。obj对象继承proto,也不可以再自定义这个属性了。如果是严格模式,这样做还会抛出一个错误
      • var proto = Object.defineProperty({}, 'foo', {
        value: 'a',
        writable: false
        }); var obj = Object.create(proto); obj.foo = 'b';
        obj.foo // 'a' 如果是严格模式,此处将抛出一个错误
    • 有一个规避方法,就是通过覆盖属性描述对象,绕过这个限制。原因是这种情况下,原型链会被完全忽视
      • var obj = Object.create(proto);
        Object.defineProperty(obj, 'foo', {
        value: 'b'
        }); obj.foo // "b"
  • enumerable(可遍历性)返回一个布尔值,表示目标属性是否可遍历
    • 如果一个属性的enumerable为false,下面三个操作不会取到该属性
      • for..in 循环
      • Object.keys() 方法
      • JSON.stringify() 方法
    • 因此,enumerable可以用来设置“秘密”属性
      • obj.x属性的enumerable为false,所以一般的遍历操作都无法获取该属性,使得它有点像“秘密”属性,
      • 但不是真正的私有属性,还是可以直接获取它的值
  • configurable (可配置性)返回一个布尔值,决定了是否可以修改属性描述对象

    • configurable为false时,value、writable、enumerable和configurable都不能被修改了
    • obj.p的configurable设置为false。然后,改动value、writable、enumerable、configurable,结果都报错
      • 注意,writable只有在false改为true会报错,true改为false是允许的
      • 至于value,只要writable和configurable有一个为true,就允许改动
      • 直接目标属性赋值,不报错,但不会成功。如果是严格模式,还会报错。
      • 可配置性决定了目标属性是否可以被删除(delete)
  • 存取器属性还可以用存取器(accessor)定义
    • 存值函数称为setter,使用属性描述对象的set属性
    • 取值函数称为getter,使用属性描述对象的get属性
      • 一旦对目标属性定义了存取器,那么存取的时候,都将执行对应的函数
      • 利用这个功能,可以实现许多高级特性,比如某个属性禁止赋值
      • var obj = Object.defineProperty({}, 'p', {
        get: function () {
        return 'getter';
        },
        set: function (value) {
        console.log('setter: ' + value);
        }
        }); obj.p // "getter"
        obj.p = 123 // "setter: 123"
    • JavaScript 还提供了存取器的另一种写法
      • var obj = {
        get p() { // 取值函数get不能接受参数
        return 'getter';
        },
        set p(value) { // 存值函数set只能接受一个参数(即属性的值)
        console.log('setter: ' + value);
        }
        };

        存取器往往用于,属性的值依赖对象内部数据的场合。

          • var obj ={
            $n : 5,
            get next() { return this.$n++ },
            set next(n) {
            if (n >= this.$n){
            this.$n = n;
            }else{
            throw new Error('新的值必须大于当前值');
            }
            }
            }; obj.next // obj.next = 10;
            obj.next // obj.next = 5; // Uncaught Error: 新的值必须大于当前值
  • 拷贝对象的所有属性到另一个对象
    • var extend = function (to, from) {
      for (var property in from) {
      to[property] = from[property];
      } return to;
      }
    • 上面这个方法的问题在于,如果遇到存取器定义的属性,会只拷贝值
    • 为了解决这个问题,我们可以通过Object.defineProperty方法来拷贝属性
    • var extend = function (to, from) {
      for (var property in from) {
      if (!from.hasOwnProperty(property)){
      // hasOwnProperty 来过滤掉继承的属性,否则会报错,因为Object.getOwnPropertyDescriptor读不到继承属性的属性描述对象
      continue;
      }
      Object.defineProperty(
      to,
      property,
      Object.getOwnPropertyDescriptor(from, property)
      );
      } return to;
      } extend({}, { get a(){ return 1 } })
      // { get a(){ return 1 } })

控制对象状态

有时需要冻结对象的读写状态,防止对象被改变

JavaScript 提供了 强度依次递增的三种冻结方法是,

  • Object.preventExtensions()

    • 可以使得一个对象无法再添加新的属性
    • var obj = new Object();
      Object.preventExtensions(obj); Object.defineProperty(obj, 'p', {
      value: 'hello'
      }); // TypeError: Cannot define property:p, object is not extensible. obj.p = 1;
      obj.p // undefined
    • Object.isExtensible() 方法
      • 用于检查一个对象是否使用了Object.preventExtensions方法。
      • 也就是说,检查是否可以为一个对象添加属性
        var obj = new Object();
        
        Object.isExtensible(obj);     // true
        Object.preventExtensions(obj);
        Object.isExtensible(obj); // fal
  • var newObj = Object.seal(obj);        密封对象,可以读写,但是不能添加新属性,不能删除属性
    • 使得一个对象既无法添加新属性,也无法删除旧属性
    • Object.seal实质是把属性描述对象的configurable属性设为false,因此属性描述对象不再能改变
    • Object.seal只是禁止新增或删除属性,并不影响修改某个属性的值
    • Object.isSealed方法用于检查一个对象是否使用了Object.seal方法
      • Object.isSealed() 为true时,Object.isExtensible方法返回false
  • var newObj  = Object.freeze(obj);

    • 可以使得一个对象无法添加新属性、无法删除旧属性、也无法改变属性的值——使得这个对象实际上变成了常量
    • 当进行修改属性、新增属性、删除属性时,这些操作并不报错,只是默默地失败。
    • 如果在严格模式下,则会报错
    • Object.isFrozen() 方法用于检查一个对象是否使用了Object.freeze方法
      • 使用Object.freeze方法以后,Object.isSealed将会返回true,Object.isExtensible返回false
      • 用途是,确认某个对象没有被冻结后,再对它的属性赋值, 就不会报错了
  • 上面的三个方法锁定对象的可写性有一个漏洞:可以通过改变原型对象,来为对象增加属性。
    • var obj = new Object();
      Object.preventExtensions(obj); var proto = Object.getPrototypeOf(obj);
      proto.t = 'hello';
      obj.t
      // hello
      
      
    • 解决方案是,把obj的原型也冻结住
      • var obj = new Object();
        Object.preventExtensions(obj); var proto = Object.getPrototypeOf(obj);
        Object.preventExtensions(proto); proto.t = 'hello';
        obj.t // undefined
    • 如果属性值是对象,上面这些方法只能冻结属性指向的对象,而不能冻结对象本身的内容
      • var obj = {
        foo: 1,
        bar: ['a', 'b']
        };
        Object.freeze(obj); obj.bar.push('c');
        obj.bar // ["a", "b", "c"]
  • 深度冻结对象成一个常量: 
  • function deepFreeze(obj){
    if(typeof obj !== "object"){
    return obj;
    }; object.freeze(obj); for(var attr in obj){
    deepFreeze(obj[attr]);
    };
    };

(74)Wangdao.com第十三天_Object 对象_属性描述对象的更多相关文章

  1. js 对象类型 (对象的属性 ,对象的方法) this 关键字

    $(function () { var observation = { init: function () { this.render();//断点:this bind :function() che ...

  2. javascript中的描述对象(Descriptor)

    对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为.Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象. 获取对象中属性描述对象 Ob ...

  3. javascript中的描述对象(Descriptor)获取和定义随笔

    最近再看了阮一峰的老师的ES6入门,发现一个有趣的东西,借此纪录以及整理下. 对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为.Object.getOwnPropertyD ...

  4. 深入理解javascript对象系列第三篇——神秘的属性描述符

    × 目录 [1]类型 [2]方法 [3]详述[4]状态 前面的话 对于操作系统中的文件,我们可以驾轻就熟将其设置为只读.隐藏.系统文件或普通文件.于对象来说,属性描述符提供类似的功能,用来描述对象的值 ...

  5. JavaScript的事件对象_其他属性和方法

    在标准的 DOM 事件中,event 对象包含与创建它的特定事件有关的属性和方法.触发的事件类型不一样,可用的属性和方法也不一样. 在这里,我们只看所有浏览器都兼容的属性或方法.首先第一个我们了解一下 ...

  6. JavaScript 对象 - 与属性的相关知识

    function inherit(p){ if(p == null) throw TypeError(); if(Object.create) return Object.create(p); var ...

  7. JS中的RegExp对象常用属性和方法

    JavaScript提供了一个RegExp对象来完成有关正则表达式的操作和功能,每一条正则表达式模式对应一个RegExp实例.有两种方式可以创建RegExp对象的实例. 使用RegExp的显式构造函数 ...

  8. JavaScript基础知识(对象、函数与对象)

    17.对象 属性:描述对象的信息  方法:描述对象的行为  封装:只关心输入和输出(不管过程如何实现) ü 对象的分类: 内置对象(原生对象): 就是JavaScript语言预定义的对象(如Strin ...

  9. 1. js数据类型_对象_函数_内存

    1. js数据类型有哪些? 基本(值)类型 Number ---- 任意数值 String ---- 任意字符串 Boolean ---- true/false undefined ---- unde ...

随机推荐

  1. 在Mac下安装mongodb

    本来想用brew一键安装的,但是一直不成功,解决了一个问题随即又抛出一个问题,后来只好老老实实去官网下载安装包了,解压到/usr/local目录下. 之前下载压缩包时忘记下载到/usr/local目录 ...

  2. 基于alpine制作php镜像

    alpine包搜索https://pkgs.alpinelinux.org/ 安装依赖库 apk add --no-cache xxx 可以基于php apline镜像自行增加或删除扩展. https ...

  3. burp Suite 模块Authz 使用方法

    这个模块是朋友告诉我的,然后进行了研究使用方法. 以下为个人理解,如有错误感谢各位纠正. 0x00 安装Authz Extender > BApp Store > Authz > i ...

  4. java8 按对象属性值分组

    Map<String, List<User>> userMap = list.stream().collect(Collectors.groupingBy(User::getG ...

  5. Python 入门基础15 --shutil、shelve、log常用模块2、项目结构

    今日内容: 一.常用模块 2019.04.10 更新 1.time:时间 2.calendar:日历 3.datatime:可以运算的时间 4.sys:系统 5.os:操作系统 6.os.path:系 ...

  6. word2vec概述

    既然是概述,那么我也只会在文中谈一点关于 Word2Vec 的思想和大概的方法.对于这个算法,如果一开始学习就深入到算法细节中,反而会陷入局部极值点,最后甚至不知道这个算法是干嘛的.在了解算法大概的思 ...

  7. 用Python进行SQLite数据库操作

    简单的介绍 SQLite数据库是一款非常小巧的嵌入式开源数据库软件,也就是说没有独立的维护进程,所有的维护都来自于程序本身.它是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经 ...

  8. Beta冲刺(2/7)

    目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(2/7) 团队部分 后敬甲(组长) 过去两天完成了哪些任务 整理博客 做了点商家数据表格 接下来的计划 做 ...

  9. vcenter新建虚拟机centos7作为虚拟机模板

    网卡选项 适配器类型算则E1000 Remote console选项 电源选项 加密 打开电源,连接iso安装系统 按一下tab键,修改网卡为eth0 点击Tab,打开kernel启动选项后,增加ne ...

  10. iOS ipa 重签名 resign

    这篇关于codesign的文章不错 https://www.objccn.io/issue-17-2/ 英文原文:https://www.objc.io/issues/17-security/insi ...