JS 对象总结

news2024/10/5 13:56:38

对象

创建对象

有两种方式:

  • 通过 new 操作符实例化一个对象,再添加属性。
let person = new Object(); 
person.name = "孤城浪人"; 
person.sayName = function() { 
 console.log(this.name); 
};

构造函数,若不需要传参,那么在实例化时可以省略后边小括号。这种方式的缺点是每个实例的属性和方法都是新创建的,实例之间无法共享方法和属性。

function Person() {
  this.name = '孤城浪人';
}
const person1 = new Person();
const person2 = new Person;
console.log(person1);//Person {name: '孤城浪人'}
console.log(person2);//Person {name: '孤城浪人'}
  • 对象字面量。这种方式更方便。
let person = { 
 name: "孤城浪人", 
 sayName() { 
 	console.log(this.name); 
 } 
};
  • 原型方式

将属性和方法定义在构造函数的原型对象上,那么任何实例都能够访问到该属性和方法,这样就实现了属性和方法的共享。

function Person() {} 
Person.prototype.name = "孤城浪人"; 
Person.prototype.age = 29; 
Person.prototype.sayName = function() { 
 console.log(this.name); 
}; 
let person1 = new Person(); 
person1.sayName(); // "孤城浪人"
let person2 = new Person(); 
person2.sayName(); // "孤城浪人"
console.log(person1.sayName == person2.sayName); // true

属性

属性分为数据属性和访问器属性。JS 中可以在给对象添加属性时可以通过定义一个描述对象来限制属性的行为,我们不能直接拿到描述对象。

数据属性

数据属性就是一个保存数据值的“键”。如下例中name就是属性孤城浪人就是值。

let person = { 
 name: "孤城浪人" 
};

描述对象的四个特性:

  • [[Configurable]]:表示属性是否可以通过 delete 删除并重新定义,是否可以修改属性的描述对象,以及是否可以把它改为访问器属性。默认为 true,如前面的例子所示。
  • [[Enumerable]]:表示属性是否可以通过 for-in 循环返回。默认为 true。
  • [[Writable]]:表示属性的值是否可以被修改。默认为 true。
  • [[Value]]:属性实际的值。默认值为 undefined。

要修改属性的默认特性,就必须使用 Object.defineProperty()方法。这个方法接收 3 个参数:

  • 要给其添加属性的对象。
  • 属性的名称和一个描述符对象。
  • 描述符对象。

如下例子,person 对象的 name 属性既不能删除(严格模式下会抛出错误)也不能修改值。注意属性一旦被定义为不可配置之后,就不能再变回可配置

let person = {}; 
Object.defineProperty(person, "name", { 
 writable: false, 
 Configurable:false,
 value: "孤城浪人" 
}); 
console.log(person.name); // "孤城浪人" 
person.name = "Greg"; 
console.log(person.name); // "孤城浪人"
delete person.name;
console.log(person.name); // "孤城浪人"

访问器属性

访问器属性只能是一个获取(getter)函数或一个设置(setter)函数,这两个函数不是必需的。在读取访问器属性值时,会调用获取函数返回一个有效的值。在写入访问器属性时,会调用设置函数将值设为新值。访问器属性也有 4 个特性描述它们的行为。

  • [[Configurable]]:表示属性是否可以通过 delete 删除并重新定义,是否可以修改属性的描述对象,以及是否可以把它改为数据属性。默认为 true。
  • [[Enumerable]]:表示属性是否可以通过 for-in 循环返回。默认为 true。
  • [[Get]]:获取函数,在读取属性时调用。默认值为 undefined。
  • [[Set]]:设置函数,在写入属性时调用。默认值为 undefined。
    访问器属性是不能直接定义的,必须使用 Object.defineProperty。下面是一个例子:
let person = { name_: '' };
Object.defineProperty(person, "name", {
  get() {
    console.log('读取函数');
    return this.name_;
  },
  set(newValue) {
    console.log('设置函数');
    this.name_ = newValue;
  }
});
person.name = '孤城浪人';
console.log(person.name_); 
console.log(person.name);
// 设置函数
// 孤城浪人
// 读取函数
// 孤城浪人

上边例子中,person 对象中有一个不愿被外部方法访问的name_属性,所以定义了访问器属性 name,通过 name 来间接读取和设置 name_

获取函数和设置函数是可选的。只定义获取函数那么修改属性会被忽略。在严格模式下,尝试写入只定义了获取函数的属性会抛出错误。只定义设置函数的属性不能读取,非严格模式下读取返回 undefined,严格模式下会抛出错误。

同时添加多个属性

由于 Object.defineProperty方法一次只能添加一个属性,当需要添加多个属性时就会变得很麻烦,因此有了 Object.defineProperties方法,可以一次添加多个属性。它接收两个参数:

  • 添加或修改属性的对象
  • 描述符对象,其属性与要添加或修改的属性一一对应。

如下例:

let person = {};
Object.defineProperties(person, {
  name_: {
    value: 'WPF'
  },
  age: {
    value: 22
  },
  name: {
    get() {
      console.log('读取函数');
      return this.name_;
    },
    set(newValue) {
      console.log('设置函数');
      this.name_ = newValue;
    }
  }
})
person.name = '孤城浪人';
console.log(person.name_);
console.log(person.name);
console.log(person.age);
// 设置函数
// WPF
// 读取函数
// WPF
// 22

注意:数据属性的 configurable、enumerable 和 writable 特性值都是 false。 所以在上边例子中可以看到修改 person.name 并没有成功。

获取属性的描述对象

前边说过了我们不能直接在 JS 中拿到属性的描述对象,但是我们可以通过 JS 提供的Object.getOwnPropertyDescriptor方法拿到属性的描述对象。

let person = {};
Object.defineProperty(person, 'name', {
  writable: false,
  value: '孤城浪人'
})
console.log(Object.getOwnPropertyDescriptor(person, 'name'));

在这里插入图片描述

同时获取多个属性的描述对象

若想获取多个属性的描述对象Object.getOwnPropertyDescriptor方法就没那么方便了,所以 ECMAScript 2017 新增了 Object.getOwnPropertyDescriptors 方法,接收一个参数:需要查询的对象。这个方法实际上会在每个属性上调用Object.getOwnPropertyDescriptor并在一个新对象中返回它们。如下例

let person = {};
Object.defineProperties(person, {
  name_: {
    value: 'WPF'
  },
  age: {
    value: 22
  },
})
console.log(Object.getOwnPropertyDescriptors(person));

在这里插入图片描述

合并对象

把源对象所有的本地属性一起复制到目标对象上,这种操作也叫“混入”(mixin)。

Object.assign方法接收一个目标对象和一个或多个源对象作为参数,将每个源对象中可枚举属性和自有属性浅复制到目标对象。符合条件的属性,本方法会使用源对象上的 [[Get]] 取得属性的值,然后使用目标对象上的 [[Set]] 设置属性的值。

如果多个源对象有相同的属性,则后面的会覆盖前面的值。不能在两个对象间转移获取函数和设置函数。

如下例就会调用 person 的 get 访问器属性并会调用目标对象 person1 的同名 set 访问器属性。且通过打印结果可以看到目标对象上并没有叫 name 的 get 访问器属性。

const person1 = {
  set name(val) {
    console.log(`set执行,拿到 ${val}`);
  }
};
const person = {
  get name() {
    console.log('get执行');
    return 'foo';
  }
};
Object.assign(person1, person);
console.log(person1)

在这里插入图片描述
注意:如果赋值期间出错,则操作会中止并退出,同时抛出错误。所以可能只会完成部分属性的复制。

const person1 = {};
const person = {
  age: 22,
  get name() {
    throw Error('出错啦!')
  },
  sex: 'man'
};
try {
  Object.assign(person1, person);
} catch (error) {
  console.log(error)
}
console.log(person1)

在这里插入图片描述

对象语法增强

Object.is

接收两个参数,判断两个参数是否相同,很像 ===

console.log(Object.is(+0, -0)); // false 
console.log(Object.is(+0, 0)); // true 
console.log(Object.is(-0, 0)); // false 
console.log(Object.is(NaN, NaN)); // true

属性值简写

属性名和变量名是一样可以,只要在对象中使用变量名即可,若未找到同名变量则会报错。

let name = '孤城浪人';
let age = 22;
let person = {
  name,
  age
}
console.log(person);

可计算属性

可计算属性可以在对象字面量中完成动态属性赋值,中括号中的内容会被当作 JavaScript 表达式求值。

注意:如果表达式抛出错误,那么之前完成的计算是不能回滚的

let myName = 'name';
function getAge() {
  return 'age';
}
let person = {
  [myName]: '孤城浪人',
  [getAge()]: 22
}
console.log(person);//{name: '孤城浪人', age: 22}

in

in 操作符会在可以通过对象访问指定属性时返回 true,无论该属性是在实例上还是在原型上。

function Person() {
  this.name = '孤城浪人';
}
Person.prototype.age = 22;
const person1 = new Person;
console.log("name" in person1);//true
console.log("age" in person1);//true
console.log(person1.hasOwnProperty('name'));//true
console.log(person1.hasOwnProperty('age'));//false

对象的迭代

Object.values & Object.entries

ECMAScript 2017 新增两个静态方法Object.valuesObject.entries接收一个对象作为参数,返回它们内容的数组。Object.values返回对象值的数组Object.entries返回键/值对的数组

function Person() {
  this.name = '孤城浪人';
  this.age = 22;
}
const person = new Person;
console.log(Object.values(person));
console.log(Object.entries(person));

在这里插入图片描述
注意,非字符串属性会被转换为字符串输出。并且这两个方法对对象属性是浅复制:

Object.keys & for in

Object.keys接收一个对象作为参数,返回包含该对象所有可枚举属性名称的字符串数组,该字符串数组不包含原型对象上的可枚举属性。for in迭代该对象和原型对象上的所有可枚举属性名称。

function Person() {
  this.name = '孤城浪人';
  this.age = 22;
}
Person.prototype.sex = 'man';
const person = new Person;
console.log(Object.keys(person));//['name', 'age']
for (let key in person) {
  console.log(key + ':' + person[key]);
}

在这里插入图片描述
注意:for-in 循环和 Object.keys的枚举顺序是不确定的,取决于 JS 引擎,可能因浏览器而异。

我是孤城浪人,一名正在前端路上摸爬滚打的菜鸟,欢迎你的关注。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/13683.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录——单词接龙(图论)

题目 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列: 序列中第一个单词是 beginWord 。 序列中最后一个单词是 endWord 。 每次转换只能改变一个字母。 转换过程中的中间单词必须是字典 wordList 中的单词。 给你两个单词 b…

AWVS的简介与安装

目录预备知识实验目的实验环境实验步骤一任务描述:AWVS的简介实验步骤二任务描述:进行AWVS10.5的安装、界面介绍和简单的使用实验步骤三任务描述:AWVS 11.x的安装与简单使用预备知识 Acunetix Web Vulnerability Scanner(简称AWV…

Qtcreator中文显示乱码问题终于解决

问题描述:Qtcreator安装好后打印中文在控制台输出乱码(自己也在网上查找了好久,终于找到解决方法了)。 原因剖析:因为项目的编码与控制台的编码不一致导致的,而qt编码设置里并没有控制台的默认编码&#xf…

华为M-LAG跨设备链路聚合技术理论讲解

目录 为什么会出现M-LAG M-LAG基本概念 M-LAG建立过程 M-LAG的协议兼容性 M-LAG的防环机制 M-LAG正常工作流量转发 单播流量转发 组播流量转发 广播流量转发 M-LAG故障场景流量转发 上行链路故障 下行链路故障 M-LAG主设备故障 Peer-link故障 M-LAG二次故障&…

Kafka部署实验

一、实验介绍 1.1实验内容 实验在Hadoop集群上部署Kafka分布式发布订阅消息系统,并完成kafka消息管理验证。 1.2实验知识点 Kafka集群部署 Kafka消息处理流程 1.3实验环境 Kafka2.11 网易云平台 1.4实验资源 资源名称存储目录Kafka安装包/opt/software/pack…

工业数采网关 工业数采模块 工业数采工业数采终端硬件

计讯物联TG462工业数据采集网关,支持工业采集、边缘计算、无线通信、远程控制、远程运维,广泛应用于智慧工业远距离通信自动化管控物联网场景。计讯工业数采网关TG462接口丰富、丰富协议库、支持主流PLC,对接第三方云平台,工业级设…

【软件测试面试题】面试官:你在工作中发现最有意义的bug?让他满意的回答......

目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 测试面试中被问的问…

iOS开发之自定义的framework添加第三方framework,lipo和ar命令看.o文件

由于需要将之前生成的mediapipe.framework添加到自己的framework中,但是很奇怪用普通的拖拽方式添加,项目工程在加载运行自己的framework时,总是找不到mediapipe.framework中的头文件,而只编译自己的framework时,也是可…

免费域名证书最新申请方式大全

目前市场环境下,可获得域名SSL证书的方式有很多,一般有付费和免费划分。对于想免费使用域名SSL证书的朋友,这里收集整理了几个常用的SSL证书申请方式。 对于SSL证书的用处,简单的来说,就是加密数据传输,使…

这么讲不怕你不懂负载均衡

现在前沿技术领域一个很有突破口和争议性的领域就是分布式系统以及高并发的解决与处理。而解决高并发其中一个很有意思的方法就是负载均衡。 那么,究竟什么才是负载均衡呢? 首先,维基百科是这样说的: 负载平衡(英语&a…

Java_多态

作者:爱塔居的博客_CSDN博客-JavaSE领域博主 专栏:JavaSE 作者简介:大三学生,希望跟大家一起进步 文章目录 目录 文章目录 一、多态概念 二、多态实现条件 三、重写 四、向上转型和向下转型 4.1 向上转型 4.2 向下转型 五、多态的…

社交电商平台的消费返利模式——共享购

实际上目前很多商家平台提到做电商平台,坚信最先第一个想到的是一些大型好像淘宝、某猫、某多多这些,但是随着社交媒体电商行业发展,大量商业运营模式及其商业平台,第一个的自然也就相对于交易返利模式的渠道,那大家在…

ubuntu中redis客户端与服务端命令、redis数据类型、字符串string、哈希hash、列表list、集合set、有序集合zset操作命令

一、NoSQL概述 NoSQL(not only SQL):泛指非关系型数据库,是一类新出现的数据库,不支持SQL语法,其存储的数据都是kv形式,存储结构与关系型数据库中的关系表完全不同 NoSQL产品种类:主要有Redis、MongoDB、…

超百万人用它生成3D头像,这项技术刚刚中选了SIGGRAPH Asia 2022

如何才能做一个和真人一样的 3D 头像? 先上传一张照片: 变成这样: 换一个人的照片: 再看一个例子: 眼镜也可以放进来: 在此基础上,还可以换上各种各样的发型、饰品,眼睛、帽子、发色…

Css定位

定位 为什么需要定位? 提问:以下情况使用标准流或者浮动能实现吗? 某个元素可以自由的在一个盒子内移动位置,并且压住其他盒子。当我们滚动窗口的时候,盒子是固定在屏幕的某个位置的 所以: 浮动可以让多…

笨办法学 Python(第三版)习题 2: 注释和#号

参考书籍 代码 # -*- coding: utf-8 -*-# A comment, this is so you can read your program later. # Anything after the # is ignored by python.print("I could have code like this.") # and the comment after is ignored# You can also use a comment to &qu…

北京外国语大学2023年上半年公派英语高级培训班开始招生

教育部指定出国留学人员培训部的“培训班结业证书”是国家留学基金委(CSC)公派项目认可的外语水平证明文件之一。近日,北京外国语大学发出2023年上半年公派英语高级培训班招生简章。为方便培训者了解情况,知识人网小编特转载如下。…

LeetCode[112]路径总和

难度:简单 题目: 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则&#xff0c…

cookie

cookie Cookie是一个客户端会话技术,是由服务器端创建,放在响应头发送到客户端保存,用于存储少量数 据,因为存放在客户端中,容易被人编造伪造,不是很安全。一般不用于存储重要信息。它是通过键值对传递信…

载波通信在电网智能化中的应用

目录载波通信在电网智能化中的应用电力载波通信特点电力载波通信在电力智能化中应用载波数据通信载波语音通信高速电力线通信(HPLC)载波通信在电网智能化中的应用 电力载波通信特点 电力载波通信(Power line Communication)即PL…