zoukankan      html  css  js  c++  java
  • 【《你不知道的JS(上卷②)》】三、对象

    三、对象:

    一)、语法:

    对象有两种形式定义:

    声明(文字)形式

    var myObj = {
        key: value
        // ...
    };
    

    构造形式

    var myObj = new Object();
    myObj.key = value;
    
    • 在声明形式中可以添加多个键/值对,但是在构造形式中必须逐个添加属性。

    1、类型:

    ​ 对象是JS的基础,JS中一共有六种主要类型。

    • string
    • number
    • boolean
    • null
    • undefined
    • object

    ​ 前五个被称为 简单基本类型,本身并不是对象,执行type of null会返回obejct,这属于JS语言的一个bug。因此 JS中并不是万物皆是对象

    ​ JS中有许多特殊的对象子类型,称之为 复杂基本类型

    • 函数就是对象的一个子类型(即可调用的对象)。JS中函数被称作“一等公民”,本质上就是因为函数就是一个对象,可以用来向另一个函数传递参数等。
    • 数组也是对象的一个子类型,具备一些额外的行为。

    2、内置对象:

    • String
    • Number
    • Boolean
    • Object
    • Function
    • Array
    • Date
    • RegExp
    • Error

    ​ 内置对象的表现形式很像其他语言的类型(type)或者类(class),(比如Java中的String类)。但是在JS中,这些只是一些内置函数(可以当作构造函数使用(参见本卷this详解中new绑定))。

    var strPrimitive = "I am a string";
    console.log(typeof strPrimitive);  // string
    console.log(strPrimitive instanceof String);  // false
    
    var strObject = new String("I am a string");
    console.log(typeof strObject);  // object
    console.log(strObject instanceof String);  // true
    
    console.log(strPrimitive.charAt(3));  // m
    
    • ​ 虽然strPrimitive在声明时只是一个字面量,只有值,而没有String的属性。但是在必要时,引擎会自动将字符串字面量转换成一个String对象。对其他的内置类型也是如此。

    三)、内容:

    ​ 对象的内容是由一些存储在特定命名位置的(任意类型的)值组成的,我们称之为属性。

    • 实际上这些值并不是存储在对象内部,在引擎内部,对象容器内部存储引用,指向这些值真正的存储位置。

    属性访问、键访问:

    var myObject = {
      a: 2
    };
    
    // 属性访问:
    console.log(myObject.a);  // 2
    // 键访问:
    console.log(myObject["a"]);  // 2
    
    • 属性名要求必须满足标识符的命名规范,而键访问可以是任何满足UTF的字符串的属性名。

    1、可计算属性名:

    主要用于ES6中的符号(Symbol)。

    2、属性与方法:

    ​ 准确来说,函数并不会属于一个对象,因此JS中的函数并不是“方法”。(即使具有this引用)。

    3、数组:

    ​ 数组也支持字符串作为键,但是使用数值下标经过了优化。

    4、复制对象:

    浅拷贝/深拷贝:

    function anotherFunction() {
      // ...
    }
    
    var anotherObject = {
      c: true
    };
    
    var anotherArray = [];
    
    var myObject = {
    a: 2,
    b: anotherObject,  // 引用
    c: anotherArray,
    d: anotherFunction 
    };
    

    浅拷贝在复制myObject的同时,也会去复制a的值,而b、c、d的值仍然是引用。

    深拷贝则会同时复制b、c、d的值。(深拷贝可能会导致循环引用,导致死循环)

    • 对于JSON安全的对象,可以使用:

      var newObj = JSON.parse(JSON.stringify(someObj));
      
    • ES6中定义了 Object.assign(..)方法来实现浅拷贝。方法的第一个参数是 目标对象,之后可以跟一个或多个 源对象。它会遍历源对象的所有 可枚举的自由键并把它们复制到目标对象。

    5、属性描述符:

    6、不变性:

    7、[[Get]]:

    ​ 属性访问并不是简单的在对象中查找该属性。而是实现了[[Get]]操作(类似于函数调用[[Get]]())。会在对象中查找是否有名称相同的属性,如果有则返回该属性的值,如果没有则沿原型链查找。如果还是找不到则会返回undefined(如果该变量在当前词法作用域中没有定义,则会抛出ReferenceError异常)。

    8、[[Put]]:

    [[Put]]流程:

    1. 属性是否是访问描述符?如果是并且存在setter就调用setter。
    2. 属性的数据描述符中writable是否是false?如果是,在非严格模式下静默失败,在严格模式下抛出TypeError异常。
    3. 如果都不是,将该值设置为属性的值。

    9、Getter和Setter:

    ​ getter和setter是隐藏函数,分别会在获取属性值、设置属性值时会被调用。

    10、存在性:

    ​ 当类似 myObject.a这样访问属性时返回undefined,可能时属性不存在,但是也有可能该属性存储的值就是undefined。

    var myObject = {
      a: 2
    };
    
    console.log("a" in myObject)  // true
    console.log("b" in myObject)  // false
    console.log(myObject.hasOwnProperty("a"));  // true
    console.log(myObject.hasOwnProperty("b"));  // false
    
    • in操作符会检查属性是否在对象及其[[Prototype]]原型链中。

    • hasOwnProperty(..)只会检查是否在对象中。

    •   Object.prototype.hasOwnProperty.call(myObject, "a");
      
      • 借用基础的hasOwnProperty方法并把它显式绑定到myObject上。
    • 枚举 enumerable

    四)、遍历:

    • for .. in循环可以用来遍历对象的可枚举属性列表。

    • 数值索引的数组,可以用标准的for循环来遍历值。

    • for .. of循环可以直接遍历数组的值而不是数组下标。

      •   arr = [1, 2, 3]
          
          for (const val of arr) {
            console.log(val)
          };
        
      • of循环首先会向被访问对象请求一个迭代器对象,然后通过调用迭代器对象的next()方法来遍历所有值。

      • 数组有内置的 @@iterator,因此of可以直接应用在数组上。我们可以使用内置的@@iterator来手动遍历数组:

        var myArray = [1, 2, 3]
        var it = myArray[Symbol.iterator]();
        
        console.log(it.next());  // { value: 1, done: false }
        console.log(it.next());  // { value: 2, done: false }
        console.log(it.next());  // { value: 3, done: false }
        console.log(it.next());  // { value: undefined, done: true }
        
      • 普通对象并没有内置的@@iterator,但是可以自己添加。

    辅助迭代器:

    ​ 接受回调函数并把它应用到数组的每个元素上,唯一的区别就是它们对于回调函数返回值的处理方式不同。

    • forEach(..):遍历数组中的所有值并忽略回调函数的返回值。
    • every(..):会一直运行直到回调函数返回false。
    • some(..):会一直运行知道回调函数返回true。
  • 相关阅读:
    【学相伴】Nginx最新教程通俗易懂-狂神说
    Linux基础知识总结(命令行)
    CentOS7 运维
    Linux 的基础知识回顾(安装vmware) ---- No.1 后面都以Centos8 为例
    Linux sudo权限提升漏洞(CVE-2021-3156)
    Flutter开发指南之理论篇:Dart语法05(单线程模型,事件循环模型,Isolate)
    矩阵的范数
    函数导出在kvm_intel.ko,kvm.ko不共享
    python 调用内部类的两种方法
    python3 字符串方法
  • 原文地址:https://www.cnblogs.com/enmac/p/13155123.html
Copyright © 2011-2022 走看看