• Javascript基础巩固系列——标准库Object对象


    全手打原创,转载请标明出处:https://www.cnblogs.com/dreamsqin/p/13714848.html, 多谢,=。=~(如果对你有帮助的话请帮我点个赞啦)

    重新学习JavaScript是因为当年转前端有点儿赶鸭子上架的意味,我一直在反思我的知识点总是很零散,不能在脑海中形成一个完整的体系,所以这次想通过再次学习将知识点都串联起来,结合日常开发的项目,达到温故而知新的效果。与此同时,总结一下我认为很重要但又被我遗漏的知识点~

    Object()方法

    可以当作工具方法使用,将任意值转为对象,如果参数为空(或者为undefinednull),返回一个空对象;如果参数是原始类型的值,会转为对应的包装对象;如果参数是一个对象,则直接返回该对象(特殊用法,用于判断变量是否为对象)。

    var obj = Object(1);
    obj instanceof Object // true
    obj instanceof Number // true
    
    // 判断变量是否为对象
    function isObject(value) {
      return value === Object(value);
    }
    
    isObject([]) // true
    isObject(true) // false
    

    Object的静态方法

    指部署在Object对象自身的方法。

    • Object.keys()Object.getOwnPropertyNames()
      参数为一个对象,返回一个数组,数组为该对象自身的(而不是继承的)所有属性名,区别是前者只返回可枚举(enumerable: true)的属性,由于 JavaScript 没有提供计算对象属性个数的方法,所以可以用这两个方法代替。
    var a = ['Hello', 'World'];
    Object.keys(a) // ["0", "1"]
    Object.getOwnPropertyNames(a) // ["0", "1", "length"]
    
    var obj = {
      p1: 123,
      p2: 456
    };
    Object.keys(obj).length // 2
    Object.getOwnPropertyNames(obj).length // 2
    
    // 获取对象的所有属性(不管是自身的还是继承的,也不管是否可枚举)
    function inheritedPropertyNames(obj) {
      var props = {};
      while(obj) {
        Object.getOwnPropertyNames(obj).forEach(function(p) {
          props[p] = true;
        });
        // 依次获取obj对象的每一级原型对象“自身”的属性,从而获取obj对象的“所有”属性,不管是否可遍历。
        obj = Object.getPrototypeOf(obj);
      }
      return Object.getOwnPropertyNames(props);
    }
    
    • Object.getOwnPropertyDescriptor()
      获取某个属性的描述对象(属性描述对象说明见下文),第一个参数是目标对象,第二个参数是一个字符串,对应目标对象的某个属性名,只能用于对象自身的属性,不能用于继承的属性。
    var obj = { p: 'a' };
    
    Object.getOwnPropertyDescriptor(obj, 'p')
    // Object { value: "a",
    //   writable: true,
    //   enumerable: true,
    //   configurable: true
    // }
    
    • Object.defineProperty()
      通过描述对象(属性描述对象说明见下文),定义或修改某个属性,然后返回修改后的对象,参数:属性所在对象、属性名字符串、属性描述对象。
    var obj = Object.defineProperty({}, 'p', {
      value: 123,
      writable: false,  // 如果原型对象的某个属性的writable为false,那么子对象将无法自定义这个属性,但可以通过defineProperty修改value来绕过限制。
      enumerable: true,
      configurable: false
    });
    
    obj.p // 123
    
    obj.p = 246;  // 正常模式下只是默默失败,严格模式(use strict)下会报错
    obj.p // 123
    
    • 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 // 123
    obj.p2 // "abc"
    obj.p3 // "123abc"
    
    • Object.create()
      可以指定原型对象(参数不能为空且必须是对象)和属性,返回一个新的对象(可以实现由一个实例对象生成另一个实例对象)。
    // 原型对象
    var A = {
      print: function () {
        console.log('hello');
      }
    };
    
    // 实例对象
    var B = Object.create(A);
    
    Object.getPrototypeOf(B) === A // true
    B.print() // hello
    B.print === A.print // true
    
    // 传入属性描述对象参数
    var obj = Object.create({}, {
      p1: {
        value: 123,
        enumerable: true,
        configurable: true,
        writable: true,
      },
      p2: {
        value: 'abc',
        enumerable: true,
        configurable: true,
        writable: true,
      }
    });
    
    // 等同于
    var obj = Object.create({});
    obj.p1 = 123;
    obj.p2 = 'abc';
    

    生成一个不继承任何属性(比如没有toStringvalueOf方法)的对象。

    var obj = Object.create(null);
    
    obj.valueOf()
    // TypeError: Object [object Object] has no method 'valueOf'
    
    • Object.getPrototypeOf()
      获取对象的Prototype对象,即原型。
    var F = function () {};
    var f = new F();
    Object.getPrototypeOf(f) === F.prototype // true
    
    // 空对象的原型是 Object.prototype
    Object.getPrototypeOf({}) === Object.prototype // true
    
    // Object.prototype 的原型是 null
    Object.getPrototypeOf(Object.prototype) === null // true
    
    // 函数的原型是 Function.prototype
    function f() {}
    Object.getPrototypeOf(f) === Function.prototype // true
    
    • Object.setPrototypeOf()
      为参数对象设置原型,返回该参数对象。它接受两个参数,第一个是现有对象,第二个是原型对象。
    var a = {};
    var b = {x: 1};
    Object.setPrototypeOf(a, b);
    
    Object.getPrototypeOf(a) === b // true
    a.x // 1
    

    Object的实例方法

    指定义在Object.prototype对象上的方法,所有Object的实例对象都继承了这些方法。

    • Object.prototype.valueOf()
      返回当前对象对应的值,默认情况下返回对象本身,主要用途是JavaScript自动类型转换时会默认调用这个方法。
    var obj = new Object();
    1 + obj // "1[object Object]"
    
    • Object.prototype.toString()
      返回当前对象对应的字符串形式,默认情况下返回类型字符串"[object object]"(第二个值表示该对象的构造函数),数值、数组、字符串、函数、Date 对象都分别部署了自定义的toString方法,覆盖了原生的Object.prototype.toString方法。
    var o = {a:1};
    o.toString() // "[object Object]"
    
    // 数值
    (10).toString() // "10"
    
    // 数组
    [1, 2, 3].toString() // "1,2,3"
    
    // 字符串
    '123'.toString() // "123"
    
    // 函数
    (function () {
      return 123;
    }).toString()
    // "function () {
    //   return 123;
    // }"
    
    // Date对象
    (new Date()).toString()
    // "Tue May 10 2016 09:11:31 GMT+0800 (CST)"
    

    特殊应用:用于判断数据类型,由于实例对象可能会自定义toString方法,覆盖掉Object.prototype.toString方法,所以可以利用call直接调用原型方法。

    Object.prototype.toString.call(value)
    
    //数值:返回[object Number]
    //字符串:返回[object String]
    //布尔值:返回[object Boolean]
    //undefined:返回[object Undefined]
    //null:返回[object Null]
    //数组:返回[object Array]
    //arguments 对象:返回[object Arguments]
    //函数:返回[object Function]
    Object.prototype.toString.call(Math) // "[object Math]"
    //Error 对象:返回[object Error]
    //Date 对象:返回[object Date]
    //RegExp 对象:返回[object RegExp]
    //其他对象:返回[object Object]
    
    //一个比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"
    
    • Object.prototype.toLocaleString()
      返回当前对象对应的本地字符串形式,主要作用是留出一个接口,让各种不同的对象实现自己版本的toLocaleString,用来返回针对某些地域的特定的值,目前ArrayNumberDate自定义了toLocaleString方法。
    var person = {
      toString: function () {
        return 'Henry Norman Bethune';
      },
      toLocaleString: function () {
        return '白求恩';
      }
    };
    person.toString() // Henry Norman Bethune
    person.toLocaleString() // 白求恩
    
    var date = new Date();
    date.toString() // "Tue Jan 01 2018 12:01:33 GMT+0800 (CST)"
    date.toLocaleString() // "1/01/2018, 12:01:33 PM"
    
    • Object.prototype.hasOwnProperty()
      判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。
    var obj = {
      p: 123
    };
    
    obj.hasOwnProperty('p') // true
    obj.hasOwnProperty('toString') // false
    
    • Object.prototype.isPrototypeOf()
      判断当前对象是否为另一个对象的原型。
    var o1 = {};
    var o2 = Object.create(o1);
    var o3 = Object.create(o2);
    
    o2.isPrototypeOf(o3) // true
    o1.isPrototypeOf(o3) // true
    
    Object.prototype.isPrototypeOf(/xyz/) // true
    Object.prototype.isPrototypeOf(Object.create(null)) // false
    
    • Object.prototype.propertyIsEnumerable()
      判断某个属性是否可枚举,只能用于判断对象自身的属性,对于继承的属性一律返回false。
    var obj = {};
    obj.p = 123;
    
    obj.propertyIsEnumerable('p') // true
    obj.propertyIsEnumerable('toString') // false
    

    属性描述对象

    JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。
    PS:value+writable:true属性与get+set不能共存,在Object.defineProperty()Object.defineProperties()参数里面的属性描述对象,writableconfigurableenumerable这三个属性的默认值都为false

     // 属性描述对象的各个属性称为“元属性”,因为它们可以看作是控制属性的属性
    {
      value: 123,  // 属性值,默认为undefined
      writable: false,  // 布尔值,表示属性值(value)是否可改变(即是否可写),默认为true
      enumerable: true,  // 布尔值,表示该属性是否可遍历,默认为true(不可遍历时for...in循环、Object.keys()、JSON.stringify会跳过该属性)
      configurable: false,  // 布尔值,表示可配置性,默认为true,控制了属性描述对象的可写性(不可配置时无法删除该属性,也不得改变该属性的属性描述对象(value属性在writable为true时除外,writable的true改false除外))
      get: undefined,  // 表示该属性的取值函数(getter),默认为undefined,取值时会调用
      set: undefined  // 表示该属性的存值函数(setter),默认为undefined,存值时会调用
    }
    
    • 存取器settergetter
      存值函数称为setter,使用属性描述对象的set属性;取值函数称为getter,使用属性描述对象的get属性。
    // 写法一(enumerable、configurable默认为false)
    var obj = Object.defineProperty({}, 'p', {
      get: function () {
        return 'getter';
      },
      set: function (value) {
        console.log('setter: ' + value);
      }
    });
    
    obj.p // "getter"
    obj.p = 123 // "setter: 123"
    
    // 写法二(更推荐,因为enumerable、configurable默认为true)
    var obj = {
      get p() {
        return 'getter';
      },
      set p(value) {
        console.log('setter: ' + value);
      }
    };
    

    对象的拷贝

    将一个对象的所有属性,拷贝到另一个对象,为了能把存取器定义的属性也成功拷贝,可以使用以下方法。

    var extend = function (to, from) {
      for (var property in from) {
        if (!from.hasOwnProperty(property)) continue;  // 过滤掉继承的属性
        Object.defineProperty(
          to,
          property,
          Object.getOwnPropertyDescriptor(from, property)
        );
      }
      return to;
    }
    
    extend({}, { get a(){ return 1 } })
    // { get a(){ return 1 } })
    

    控制对象状态

    有时需要冻结对象的读写状态,防止对象被改变(但有漏洞:可以通过改变原型对象,来为对象增加属性;如果属性值是对象,就只能冻结属性指向的对象(即无法指向其他值),而不能冻结对象本身的内容)。JavaScript 提供了三种冻结方法,最弱的一种是Object.preventExtensions,其次是Object.seal,最强的是Object.freeze

    • 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) // false
    
    • Object.seal()
      使得一个对象既无法添加新属性,也无法删除旧属性,实质是把属性描述对象的configurable属性设为false
    var obj = { p: 'hello' };
    Object.seal(obj);
    
    delete obj.p;
    obj.p // "hello"
    
    obj.x = 'world';
    obj.x // undefined
    
    • Object.isSealed()
      用于检查一个对象是否使用了Object.seal方法。
    var obj = { p: 'a' };
    
    Object.seal(obj);
    Object.isSealed(obj) // true
    Object.isExtensible(obj) // false
    
    • Object.freeze()
      可以使得一个对象无法添加新属性、无法删除旧属性、也无法改变属性的值,使得这个对象实际上变成了常量。
    var obj = {
      p: 'hello'
    };
    
    Object.freeze(obj);
    
    obj.p = 'world';
    obj.p // "hello"
    
    obj.t = 'hello';
    obj.t // undefined
    
    delete obj.p // false
    obj.p // "hello"
    
    • Object.isFrozen()
      用于检查一个对象是否使用了Object.freeze方法。
    var obj = {
      p: 'hello'
    };
    
    Object.freeze(obj);
    Object.isFrozen(obj) // true
    Object.isExtensible(obj) // false
    

    参考资料

    JavaScript 语言入门教程 :https://wangdoc.com/javascript/index.html

  • 相关阅读:
    jQuery radio的取值与赋值
    jquery 单击选中 再次选中取消选中
    jqweui 正在加载样式的用法
    html5 横向滑动导航栏
    关于css清除元素浮动的方法总结(overflow clear floatfix)
    JavaScript中常用的事件
    baiduMap试手《办理进京证和市区警察查询进京证的地址浏览》
    原生JavaScript常用本地浏览器存储方法五(LocalStorage+userData的一个浏览器兼容类)
    原生JavaScript常用本地浏览器存储方法四(HTML5 LocalStorage sessionStorage)
    原生JavaScript常用本地浏览器存储方法三(UserData IE Only)
  • 原文地址:https://www.cnblogs.com/dreamsqin/p/13714848.html
Copyright © 2020-2023  润新知