最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 深入对象(详)

    正文概述 掘金(coolFish)   2021-03-02   684

    昨天刚过的情人节,相信很多人都和对象出门吃饭了,但是你真的了解对象吗,快来自我校验一番把,看完之后真正的理解对象。

    一,基础

    什么是对象

    对象是用来存储键值对和更加复杂的实体,我们可以通过使用带有可选 属性列表 的花括号 {…} 来创建对象。一个属性就是一个键值对(“key: value”),其中键(key)是一个字符串(也叫做属性名),值(value)可以是任何值

    我们可以吧对象想象成图书馆, 每一本书都有自己的号码 (key),这样图书管理员就可以通过号码(也就是 key)来找到对应的图书做出对应的操作。

    如何创建对象

    1. 构造函数
    let people = new Object(); // “构造函数” 的语法
    
    1. 字面量
    let user = {};  // “字面量” 的语法
    
    

    我们可以在创建对象的时候,立即将一些属性以键值对的形式放到 {} 中.

    let people = {
      name: 'coolFish',
      age: '25'
    };
    

    我们可以看到我们字面量的形式创建了一个对象,对象有两个属性,都是键值对的形式。 属性的键位于冒号左边,属性的值在冒号的右边。 在 people 对象中,有两个属性

    1. 第一个键是 name,值是 coolFish。
    2. 第二个键是 age,值是25。

    生成的people可以想象成一个假人,他有名字和年龄两个属性。我们可以随时添加,删除和读取他的属性,通过点符号可以访问对象的属性值。

    // 读取文件的属性:
    alert( people.name ); // coolFish
    alert( people.age ); // 25
    

    属性的值可以是任意类型,让我们加个布尔类型

    people.study = true;
    

    我们可以用 delete 操作符移除属性

    delete people.age;//再访问 age ,就是 undefined
    

    const 声明的对象可否被修改?

    const people = {
      name: "coolFish"
    };
    
    user.name = "Pete"; // (*)
    
    alert(user.name); // Pete
    

    小结:按理来说常量是不可变得,应该报错,但实际没有,这是因为 const 声明仅固定了 people 的值,而不是值里面的内容。当我们尝试将 people 作为一个整体进行赋值的时候,const 会报错。

    方括号取值

    当面对多词属性,点符号取值就不可取了,这时候可以使用方括号取值。

    let user = {};
    
    //设置
    user["likes birds"] = true;
    
    //读取
    
    //报错
    user.likes birds = true 
    
    //true
    alert(user["likes birds"]); 
    
    //跟 user["likes birds"] = true; 一样
    let key = "likes birds";
    user[key] = true;
    
    //删除
    delete user["likes birds"];
    

    计算属性

    当创建一个对象时,我们可以在对象字面量中使用方括号。这叫做 计算属性

    let fruit = prompt("Which fruit to buy?", "banana");
    
    let bag = {
      [fruit]: 25, // 属性名是从 fruit 变量中得到的
    };
    
    alert( bag.banana ); // 25 
    
    

    我们可以在方括号中使用更复杂的表达式

    let fruit = 'apple';
    let bag = {
      [fruit + 'Computers']: 5 // bag.appleComputers = 5
    };
    
    

    大部分时间里,当属性名是已知且简单的时候,就使用点符号。如果我们需要一些更复杂的内容,那么就用方括号。

    属性值简写

    实际开发中,我们会把已存在的变量作为属性名。

    function makeUser(name, age) {
      return {
        name: name,
        age: age,
        // ……其他的属性
      };
    }
    
    let user = makeUser("coolFish", 25);
    alert(user.name); // coolFish
    
    

    属性存在性测试,"in" 操作符

    let user = { name: "John", age: 30 };
    
    alert( "age" in user ); // true,user.age 存在
    alert( "blabla" in user ); // false,user.blabla 不存在。
    
    

    我们用 in 可以很简单的判断该对象是否拥有该属性,in 的左边是属性名,一般是带引号的字符串,如果没有引号,意味着是一个变量。

    注意 in 是有限制的,in 会查找原型链上的同名方法和属性

    let user = { name:"coolFish",age:"24"}
    console.log(user.sex)  //undefined
    user.__proto__.sex = "男"
    console.log(user)   //{ name:"coolFish",age:"24"}
    console.log(user.sex) //男
    
    

    我们可以看到,原型链上的属性会影响 in 的判断。

    for...in 循环

    let user = {
      name: "John",
      age: 30,
      isAdmin: true
    };
    
    // 对此对象属性中的每个键执行的代码
    for (let key in user) {
      // keys
      alert( key );  // name, age, isAdmin
      // 属性键的值
      alert( user[key] ); // John, 30, true
    }
    
    

    使用这种操作,我们可以轻松的讲对象里的属性的键值取出来。

    二,对象的引用与应用

    对象的引用和复制

    和原始值复制不同,对象复制不会开辟新的存储空间,而是给新的对象变量赋值该对象在内存中的地址 ,换句话说就是对该对象的引用。

    let one = "这是原始值一";
    let two = one;
    
    

    最后我们会有两个独立的变量,每个都存储着字符串 "这是原始值一" 深入对象(详) 但是对象不是这样的,复制对象,等于是创建一个对象变量,然后把对象在内存中的地址赋值给他。

    let one = { name: "coolFish" };
    let two = one; // 复制引用
    
    

    深入对象(详) 我们可以看到对象仍然只有一个,但是现在有两个引用它的变量,如果我们通过其中一个变量来访问对象,并且修改它的内容,那么另外一个变量去访问内容时也能发现内容发生变化,因为他们最后找到的是同一个东西。

    let one = { name: "coolFish" };
    let two = one; // 复制引用
    two.name = "ulgyFish"
    console.log(one.name)  //"ulgyFish"
    
    

    两个对象比较

    仅仅当两个对象变量指向同一个对象时,他们才相等

    例如下面,这两个对象变量,都是指向同一个空对象,所以相等

    let a = {};
    let b = a; // 复制引用
    
    alert( a == b ); // true,都引用同一对象
    alert( a === b ); // true
    
    

    我们看下例,两个空对象并不相等,因为他们是两个独立的空对象

    let a = {};
    let b = {}; // 两个独立的对象
    
    alert( a == b ); // false
    
    

    对象的拷贝

    我们通过上面案例知道,直接通过赋值操作,只是赋值了对象的引用,并不是真的创建了一个新的对象,如果我们想要复制一个对象,应该怎么做呢?

    1. 创建一个新的对象,然后通过遍历要复制的那个对象的所有属性的结构,在原始类型值得层面,将其复制到新对象,以复制已有对象的结构。
    let user = {
      name: "coolFish",
      age: 24
    };
    
    let clone = {}; // 新的空对象
    
    // 将 user 中所有的属性拷贝到其中
    for (let key in user) {
      clone[key] = user[key];
    }
    
    // 现在 clone 是带有相同内容的完全独立的对象
    clone.name = "semlinker"; // 改变了其中的数据
    
    alert( user.name ); // 原来的对象中的 name 属性依然是 coolFish
    
    
    1. 通过使用 Object.assign 方法来达成
    Object.assign(dest, [src1, src2, src3...])
    
    

    该方法接受2个参数,参数1是目标对象,参数2是一个数组,数组中是要拷贝的对象。 深入对象(详) 我们看到参数2对象中的属性,被拷贝到我们的目标对象了,因为第二个参数是数组,So我们可以用此方法合并对象

    let user = { name: "coolFish" };
    
    let userAge = { age: 24 };
    let userSex = { sex: "男"};
    
    // 将 userAge 和 userSex 中的所有属性都拷贝到 user 中
    Object.assign(user, userAge, userSex);
    // 现在 user = { name: "John",  age: 24 , sex: "男" }
    
    

    我们可以看到,3个对象合并成一个对象了,但是当属性名重复,那么他会被覆盖

    let user = { name: "coolFish" };
    
    Object.assign(user, { name: "semlinker" });
    
    alert(user.name); // 现在 user = { name: "semlinker" }
    
    

    我们可以用Object.assign代替 for... in循环来进行克隆

    let user = {
      name: "coolFish",
      age: 24
    };
    
    let clone = Object.assign({}, user);
    
    

    浅拷贝

    当 user 的属性不为原始类型。属性可以是对其他对象的引用。那应该怎样处理它们呢?

    let user = {
      name: "coolFish",
      sizes: {
        height: 182,
        width: 50
      }
    };
    
    let clone = Object.assign({}, user);
    
    alert( user.sizes === clone.sizes ); // true,同一个对象
    
    // user 和 clone 分享同一个 sizes
    user.sizes.width++;       // 通过其中一个改变属性值
    alert(clone.sizes.width); // 51,能从另外一个看到变更的结果
    
    

    为了解决此问题,我们应该使用会检查每个 user[key] 的值的克隆循环,如果值是一个对象,那么也要复制它的结构。这就叫“深拷贝”。 我们可以用递归来实现。或者不自己造轮子,使用现成的实现,例如 JavaScript 库 lodash 中的 _.cloneDeep(obj)。

    小结:对象通过引用被赋值,对象变量存储的并不是对象的值,而是对这个对象的引用,因此拷贝的是该对象的引用,而不是对象本身。

    三,对象中的 this

    通常,对象方法需要访问对象中存储的信息才能完成其工作。 例如:下例中的 user.sayHi() 方法中的代码就需要用到对象中的属性

    let user = {
      name: "coolFish",
      age: 24,
    
      sayHi() {
        // "this" 指的是“当前的对象”
        alert(this.name+"说:你好");
      }
    
    };
    
    user.sayHi(); // coolFish说:你好
    
    

    this 的值就是在点之前的这个对象,即调用该方法的对象。 这里的user.sayHi() 执行过程中,this的值是 user

    let user = { name: "coolFish" };
    let admin = { name: "semlinker" };
    
    function sayHi() {
      alert( this.name );
    }
    
    // 在两个对象中使用相同的函数
    user.f = sayHi;
    admin.f = sayHi;
    
    // 这两个调用有不同的 this 值
    // 函数内部的 "this" 是“点符号前面”的那个对象
    user.f(); // coolFish(this == user)
    admin.f(); // semlinker(this == admin)
    
    admin['f'](); // semlinker(使用点符号或方括号语法来访问这个方法,都没有关系。)
    
    
    1. 我们可以看到,虽然是调用同一个方法,但是在不同的对象中调用,所以他们的 this 也不同
    2. 在 JavaScript 中,this 是“自由”的,它的值是在调用时计算出来的,它的值并不取决于方法声明的位置,而是取决于在“点符号前”的是什么对象。

    总结:

    关于对象的总结暂时这些,如有补充,欢迎小伙伴门指出。


    起源地下载网 » 深入对象(详)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元