zoukankan      html  css  js  c++  java
  • JS简记-对象

    js中有六大类型:string、number、boolean、object、null、undefined。

    console.log(typeof "123");//string
    console.log(typeof 123);//number
    console.log(typeof true);//boolean
    console.log(typeof {});//object
    console.log(typeof null);//object
    console.log(typeof undefined);//undefined

    其中string、number、boolean、null、undefined称为简单基本类型,object为对象类型。js有两种生成对象的方式,一种是字面量(var o = {...}),另一种是构造调用(var o = new Array(...)),通常我们都会使用第一种字面量形式。访问对象属性也有两种方式,一种是通过“.”访问,另一种是通过“[]”访问,通常使用前者访问,但通过后者可以定义/访问动态属性名,功能更加强大(比如obj[a+b]=1)。

    最基础的类型为对象类型的对象为Object,Object有很多子对象,比如String、Number、Boolean,Function、Array等,String、Number、Boolean可以看成是基本类型string、number、boolean的包装类型,js引擎在执行时如果有必要会自动将基本类型“打包”成其相应的对象类型。

     通常情况下,所有的对象类型都会“继承”Object对象,但也有例外的情况:

    var a1 = {};
    var a2 = Object.create(null);

    查看window的这两个属性,a2便不“继承”Object对象:

    String

    常用方法:concat,indexOf,lastIndexOf,replace,split,substr,substring等。

    Number

    常用方法:toFix,toString等。

    Boolean

    Array

    常用方法:concat,join,push,pop,shift,sort

    数组在使用“[]”操作属性时,如果"[]"中的内容为字符串型的数字则会被视为数字,从而对数组元素进行操作。而普通对象在使用“[]”操作属性时,则会将“[]”中的数字视为字符串,从而对对象属性进行操作。

    var arr = ["a"];
    arr.push("b");
    console.log(arr[1]);//b
    console.log(arr["1"]);//
    console.log(arr.length);//2
    
    var obj = {0: "a"};
    obj[1] = "b";
    console.log(obj[1]);//b
    console.log(obj["1"]);//b

    Function

    Date

    RegExp

    Error

    复制对象内容

    var newObj = JSON.parse(JSON.stringify(obj));

    ES6提供的浅复制方法Object.assign(target, ......sources)

    var newObj = Object.assign(Object.create(null), obj1, obj2);

     数据描述符访问描述符

    从ES5开始,我们可以通过Object.getOwnPropertyDescriptor获取对象的属性描述符(描述对象属性的一个数据结构(对象),又分为数据描述符和访问描述符)

    var obj = {
        a: "hello"
    }
    console.log(Object.getOwnPropertyDescriptor(obj, "a"));

    控制台打印如下,可以看到一个对象的某个属性的数据描述符是一个Object的子对象,且一个数据描述符对象拥有value、writable、enumerable、configurable四个属性。

    同样的,我们可以对属性描述符进行设置:

    var obj = {};
    Object.defineProperty(obj, "a", {
        value: 2,
        writable: true,
        configurable: true,
        enumerable: true
    });
    obj.a;// 2

    我们在访问对象的属性时,看似是直接操作于该属性,实则js引擎会通过调用内部的[[Get]]/[[Put]]逻辑对属性进行操作,这时属性描述符对象就有用了。比如obj.a=3,这时就会走[[Put]]逻辑,首先判断a属性是否存在,如果存在,[[Put]]会判断a属性是否可写,即writable是否为true,如果为true才会更新a的值。

    通过数据描述符,我们就可以对对象属性进行访问控制了,比如是否可更新,是否可枚举(通过for in遍历)。ES5进一步提供了一些方法用于控制对象属性的访问策略,比如可以通过Object.preventExtensions(..)、Object.seal(..)、Object.freeze(..)等函数设置对象(及其属性)的不可变性级别。

    [[Get]]/[[Put]]是js引擎内部逻辑,我们是否可以重写某些属性的[[Get]]/[[Put]]逻辑呢?ES5中,可以使用getter/setter重写默认逻辑(也可以这样理解,[[GET]]/[[PUT]]首先会尝试getter/setter,如果二者未定义则使用数据描述符,访问描述符和数据描述二者只能定义其一),getter/setter就被称为访问描述符

     1 obj = {
     2     a: "hello",
     3     get a(){//必须放在a: "hello"之后,否则会被默认逻辑覆盖
     4         return "world";
     5     },//默认enumerable:true, configurable:true
     6 }
     7 console.log(obj.a);//world
     8 //or
     9 Object.create(null, {
    10     {
    11         a: {
    12             get: function(){return "world";},
    13             set: function(value){this._a_ = value},
    14             enumerable: true,
    15             configurable: true,//不能对访问描述符设置writable和value
    16         }
    17     }
    18 });    

    对象的遍历

    我们知道数组可以使用for in,通过数组元素的索引来遍历数组。ES6中数组对象内部提供了一个迭代器(可以通过属性名Symbol.iterator查看,是一个native code),可以通过该迭代器实现for of遍历:

    var arr = ["a", "b", "c"];
    for(let v of arr){
        console.log(v);//通过for of得到的是数组的值,而不需要再通过索引来找值了
    }

    除了for of,ES5数组还有forEach、every、some等遍历函数。

    js对象很像一个map,key就是属性名,value就是属性值,那么普通对象是否可以像数组一样使用for of进行遍历呢?js并没有为普通对象提供类似的迭代器,我们只能使用for in通过数组元素的索引对数组进行遍历。但我们可以自定义一个迭代器,通过该迭代器就可以使用for of了:

     1 function generateIterator(){
     2     var obj_ = this;
     3     var keys = Object.keys(obj);
     4     var i = 0;
     5     return {
     6         next: function(){
     7             return {
     8                 value: obj_[keys[i++]],
     9                 done: i>keys.length
    10             }
    11         }
    12     }
    13 }
    14 var obj = {
    15     a: "hello",
    16     b: "world"
    17 };
    18 Object.defineProperty(obj, Symbol.iterator
    19     , {
    20         writable: false,
    21         enumerable: false,
    22         configurable: true,
    23         value: generateIterator
    24     });
    25 //手动遍历
    26 for(let ite=obj[Symbol.iterator](), next=ite.next(); !next.done; next=ite.next()){
    27     console.log(next.value);
    28 }
    29 //for of
    30 for(var v of obj){
    31     console.log(v);
    32 }
  • 相关阅读:
    day1-字符串拼接、表达式、break和continue
    ssh免密登录
    1-5 文档的基本 CRUD 与批量操作
    1-4 安装logstash
    1-3 安装cerebro
    1-2 kibana 7.5.1 安装配置
    1-1 elasticsearch7.5 集群搭建 es 7
    生产环境k8s集群搭建
    Gearman任务分布系统部署windows平台_使用Cygwin
    [转载]单元测试之道(使用NUnit)
  • 原文地址:https://www.cnblogs.com/holoyong/p/8976951.html
Copyright © 2011-2022 走看看