zoukankan      html  css  js  c++  java
  • 对象

    原文地址:https://wangdoc.com/javascript/

    概述

    简单的说,对象就是一组键值对的集合。

    键名

    对象的所有键名都是字符串(ES6又引入了Symbol值也可以作为键名),所以加不加引号都可以。但是如果键名不符合标识符的条件,必须要加上引号,否则会报错。属性值还可以是对象,就形成了链式引用。

    var object1 = {};
    var object2 = {bar : "hello"};
    object1.foo = object2;
    object1.foo.bar // "hello"
    

    上面的代码直接对object2对象的foo属性赋值,结果就在运行时创建了foo属性。

    对象的引用

    如果不同的变量指向同一个对象,那么它们都是这个对象的引用,也就是说指向了同一块内存。修改其中一个变量,会影响到其他的所有变量,如果取消一个变量对原对象的引用,不会影响到其他的变量。

    var object1 = {};
    var object2 = object1;
    
    object1.a = 1;
    object2.a // 1
    
    object1 = 1;
    object2 // {}
    

    但是这种引用只局限于对象,如果两个变量指向同一个原始类型的值。那么,变量是值得拷贝。

    var x = 1;
    var y = x;
    
    x = 2;
    y // 1
    

    表达式还是语句

    对象采用大括号表示,这就导致了一个问题,如果行首是一个大括号,它到底是表达式还是语句?

    { foo: 123 }
    

    JavaScript引擎读到上面的这行代码,会发现可能有两种含义。

    • 这是一个表达式,表示一个包含foo属性的对象;
    • 这是一个代码块,label为foo,指向表达式123。
      为了避免这种歧义,V8引擎规定,如果行首是大括号,一律解释为对象。不过为了避免歧义,最好加上小括号。这种差异在eval语句中反应的最为明显。
    ({ foo: 123 })
    eval("{foo: 123}") // 123 代码块
    eval("({foo: 123})") // {foo: 123} 对象
    

    属性的操作

    属性的访问

    有两种方式

    • 点运算符
    • 方括号运算符
    var obj = {
        p: "Hello World!"
    };
    obj.p // "Hello World!"
    obj["p"] // "Hello World!"
    

    注意使用方括号运算符时,属性名必须加引号,否则会当做变量处理

    var foo = "bar";
    var obj = {
        foo: 1,
        bar: 2
    };
    
    obj.foo // 1
    obj.[foo] // 2
    

    方括号运算符内部可以使用表达式,纯数字键可以不加引号,会自动转成字符串,但是纯数字键名不能使用点运算符,只能使用方括号运算符

    obj["hello" + "world"]
    var obj2 = {
        0.7: "hello"
    }
    obj2[0.7] // "hello"
    obj2["0.7"] // "hello"
    

    属性的赋值

    点运算符和方括号运算符不仅可以用来访问,还可以用来赋值。
    JavaScript允许属性的后绑定,也就是说,你可以在任意时刻新增属性,没必要在定义对象的时候,就定义好属性。

    var obj = { p : 1};
    // 等价于
    var obj = {};
    obj.p = 1;
    ### 属性的查看
    查看一个对象所有的属性,可以使用<font color=red>Object.keys()</font>方法。
    

    var obj = {
    key1: 1,
    key2: 2
    };
    Object.keys(obj); // ["key1", "key2"]

    ### 属性的删除:delete关键字
    <font color=red>delete</font>关键字用于删除对象的属性,删除成功后返回<font color=red>true</font>。**注意,删除一个不存在的属性,<font color=red>delete</font>不报错,而且返回<font color=red>true</font>,只有一种情况,<font color=red>delete</font>会返回false,那就是这个属性存在,且不能删除。
    ```js
    var obj = { p: 1 };
    Object.keys(obj); // ["p"]
    delete obj.p; // true
    obj.p // undefined
    Object.keys(obj); // []
    delete obj.o // true
    
    var obj = Object.defineProperty({}, "p", {
        value: 123,
        configurable: false
    });
    obj.p // 123
    delete obj.p // false
    

    另外,需要注意的是,delete只能删除对象本身的属性,无法删除继承的属性。

    var obj = {};
    delete obj.toString // true
    obj.toString // function toString() { [native code] }
    

    上面代码中,toStringobj继承的属性,虽然返回true,但该属性并没有被删除。说明**即使delete返回true,该属性依然可能读到值。

    属性是否存在:in预算符

    in运算符用于检查对象是否包含某个属性,包含返回true,否则返回falsein运算符的一个问题是,它不能识别哪些属性是自身的,哪些是继承的。这时,可以用对象的hasOwnProperty方法判断一下。

    var obj = {p: 1};
    "p" in obj // true
    "toString" in obj // true
    
    if ("toString" in obj) {
        console.log(obj.hasOwnProperty("toString")) // false
    }
    

    属性的遍历: for ... in循环

    var obj = {a: 1, b: 2, c: 3};
    
    for (var i in obj) {
        console.log("key: " + i);
        console.log("value: " + obj[i]); // 注意是obj[i]
    }
    注意点:
    * 它遍历的是所有可遍历的属性,会跳过不可遍历的属性
    * 它不仅遍历对象自身的属性,还遍历继承的属性
    举例来说,对象都继承了toString属性,但是<font color=red>for...in</font>循环不会遍历这个属性。
    一般情况下,都是只想遍历自身的属性,所以使用<font color=red>for...in</font>的时候,应该结合使用<font color=red>hasOwnProperty</font>方法。
    ```js
    var person = {...}
    for (var key in person) {
        if (person.hasOwnProperty(key)) {
            console.log(key);
        }
    }
    

    with语句

    with语句格式如下

    with (对象) {}
        语句;
    }
    它的作用是操作同一个对象的多个属性时,提供一些书写的方便。
    

    var obj = {
    p1: 1,
    p2: 2,
    };
    with (obj) {
    p1 = 4;
    p2 = 5;
    }
    // 等同于
    obj.p1 = 4;
    obj.p2 = 5;

    注意,**如果<font color=red>with</font>区块内部有变量的赋值操作,必须是当前对象已经存在的属性,否则会创造一个当前作用域的全局变量。
    ```js
    var obj = {};
    with (obj) {
        p1 = 4;
    }
    obj.p1 // undefined
    p1 // 4
    

    这是因为with区块没有改变作用域,它的内部依然是当前作用域。这造成with语句一个很大的弊病,就是绑定对象不明确

    with (obj) {
        console.log(x);
    }
    

    单纯从上面的代码块,根本无法判断x到底是全局变量,还是对象obj的一个属性。建议不要使用with语句,可以考虑用一个临时变量代替

    with (obj1.obj2.obj3) {
        console.log(p1 + p2);
    }
    // 写成
    var temp = obj1.obj2.obj3;
    console.log(temp.p1 + temp.p2);
    
  • 相关阅读:
    React+Redux仿Web追书神器
    关于贝塞尔曲线的故事
    420小时学习代码之后:如何教你免费自学Python
    学问Chat UI(3)
    学问Chat UI(1)
    Binder进程间通信详解
    Handler源码分析
    学问Chat UI(4)
    WebPack错误集
    React问题集序
  • 原文地址:https://www.cnblogs.com/chris-jichen/p/9930079.html
Copyright © 2011-2022 走看看