《无所不能的JavaScript · 对象简介》

news2024/9/23 9:32:08

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍

文章目录

      • 写在前面的话
      • 对象的概述
      • 对象的三个属性
      • 对象的方法
      • 对象的创建
      • 属性的操作
      • Object 常用方法
      • 总结陈词

CSDN.gif

写在前面的话

本篇博文再次回归JavaScript系列,不知道是不是Java写多了,偶尔换JavaScript就和打鸡血一样兴奋。
这里先介绍一下 JS 对象,现今的后端开发人员,往往都在与 Vue、ElementUI 操作打交道,对JavaScript的了解知之甚少,JS 也有对象吗?那不是 Java 的概念,JS 也有吗?

推荐文章:
《无所不能的JavaScript · prototype 原型链》
《无所不能的JavaScript:ES6入门》
《无所不能的JavaScript · 异步编程》
《程序猿学会 Vue · 基础与实战篇》


对象的概述

  • 对象是 JavaScript 的基本数据类型,可以看做是字符串到值的映射(key-value)的无序集合;
  • 除了字符串、数字、true、false、null和undefined外,JavaScript 中的值都是对象。
  • 对象除了保持自有的属性,还可以从一个称为原型的对象继承属性,这种原型式继承,是JavaScript 的核心特征。
  • 如果变量x是对象,那么var y = x,对y的修改会影响到x,这里x和y都是对象的引用(类似Java的传址)。
  • 可以通过对象直接量、关键字new和Object.create()函数三种方式创建对象,下面会详细介绍。

对象的三个属性

每一个对象都有与之相关的原型(prototype)、类(class)和可扩展性(extensible)。

原型 prototype:
在ECMAScript5 中,使用 Object.getPrototype() 来获取原型。
检测原型可以使用 isPrototypeOf() 功能和 instanceof 运算符类似,前者是函数用法。
原型的若干规则说明:
规则1:除null外的每一个JS对象,都和原型相关联,对象都从原型继承属性;
规则2:Object的原型不继承任何属性(即Object.prototype没有原型),除此之外的所有对象都是普通对象,具有原型;
规则3:所有内置构造函数具有继承自Object.prototype的原型,如Date等,因此,new Date()创建的对象同时继承Object.prototype和Date.prototype的属性;
规则4:所有通过对象直接量创建的对象都具有同一个原型对象,可以使用Object.prototype获得对原型对象的引用;

var a = {a:1}; //直接量方式创建对象
Object.prototype.isPrototypeOf(a);  //返回true
arr instanceof Object;  //返回true
a.constructor.prototype.isPrototypeOf(a);  //返回true

规则5:通过关键字new+构造函数调用创建的对象,它的原型是构造函数的prototype属性的值,例如,new Array()创建的对象的原型就是Array.prototype,当然了Object.prototype也是;

类 class :
对象的类属性是一个字符串,可以使用toString()获取,获得这样格式的字符串:[object class],再截取第八位到倒数第二位即可。

// 获取变量的类型
function classof(o) {
  if(o === null) return "Null";
  if(o === undefined) return "Undefined";
  return Object.prototype.toString.call(o).slice(8,-1);
}

对象序列化
对象序列化是指将对象转换为字符串,也可将字符串还原为对象。
ECMAScript5 提供了JSON.stringify()和JSON.parse()用来序列化和反序列化。
ECMAScript3 引入 json2.js,就具备了类似功能,IE低版本可能需要引入。


对象的方法

所有对象都从 Object.prototype 继承属性,这些继承属性主要是方法。
常用的有 tostring(),toLocaleString(),toJSON(),valueOf(),isPrototypeOf ,hasOwnProperty() 和 propertyIsEnumerable()等等。

  • isPrototypeOf():检测原型,用法Object.prototype.isPrototypeOf(a);
  • hasOwnProperty():判断自有属性,用法o.hasOwnProperty(“x”);
  • propertyIsEnumerable():判断可枚举的自有属性,用法o. propertyIsEnumerable(“x”);
  • tostring():该方法没有参数,它将返回一个表示调用这个方法的对象的字符串。
  • valueOf():JavaScript中valueOf函数方法是返回指定对象的原始值。
  • toJSON():Object.prototype实际上没有定义此方法,但对于需要执行序列化的对象来说,JSON.stringify()方法会调用该方法。

valueOf 和 tostring 的区别
valueOf 偏向于运算,toString偏向于显示,自定义对象一般都重写他们。
1、 在进行对象转换时(例如:alert(a)),将优先调用toString方法,如若没有重写toString将调用valueOf方法,如果两方法都不没有重写,但按Object的toString输出。
2、 在进行强转字符串类型时将优先调用toString方法,强转为数字时优先调用valueOf。
3、 在有运算操作符的情况下,valueOf的优先级高于toString。
4、 valueOf如果返回本身的话(而不是原始值),一般会去使用toString。


对象的创建

【方式一:对象直接量】
示例1:
image.png

示例2:

var a = {
    b:1,    ---注意这里是逗号
    toString:function(){ return 1;}  //可以重写toString方法为自己的方法
}
alert(a); //JS的alert输出对象,对象调用toString方法,比如这里就是a.toString();

说明如下:
规则1:属性名可以是JS标识符也可以是字符串直接量(有无引号皆可),属性值任意;
规则2:属性名如果用到空格,连字符或者是保留字,则必须用字符串表示;
规则3:对象直接量是一个表达式,每次运算都会创建并初始化一个新的对象,这点注意了;

【方式二:new关键字+构造函数】

var o = new Object; //创建一个空对象
var a = new Array; //创建一个空数组,和[]一样

说明如下:
规则1:JS语言核心中的原始类型都包含内置构造函数;
规则2:除了这些内置构造函数外,也可以使用自定义构造函数来初始化,如例2;

function employee(name,job,born){
    this.name=name;
    this.job=job;
    this. born = function(){return  born};
}
var bill=new employee("Bill Gates","Engineer",1985);  //这里var不能写成employee

构造函数可以使用prototype关键字为其赋予额外的属性和方法,在对象生成之前或者之后都有效。

var path = function(){
    return {
        anchor:0,
        init:function(_anchor){
            this.anchor=_anchor;
        }
    }
};

此种方式定义,更有利于模块化管理,封装多个属性和方法,可以构造出多个(写成function path() 也是一样的)。
使用:var a = path(); a.init();
这里的init方法不可替换回var init =function(){…},因为此处return的是一个object,object里面都是key-value键值对。
var init =function(){…},可以放在return外面,但是只能作为私有属性,在path函数里面使用。

【方式三:Object.create()】
create是一个静态函数,参数是一个对象的原型,这种方式比较少用。

var o1 =Object.create({x:1}); //o1继承了属性x
var o2 =Object.create(null); //o2不继承任何属性和方法,包括toString方法
var o3 = Object.create(Object.prototype); //效果和new Object以及{}一样

属性的操作

【属性访问表达式】
可以通过点(.)或者方括号([])运算符来进行属性访问,也称为属性访问表达式。
语法1:expression . identifier
语法2:expression [expression ]
语法解析:
运算符左侧是一个表达式,它返回一个对象/数组,第一种方式不适合数组;
对于点来说,右侧必须是一个以属性名称命名的简单标识符;
对于方括号来说,右侧必须是一个计算结果为字符串的表达式,这个字符串就是属性的名称(对于数组来说,右侧是要访问数组元素的索引)。
运作解析:
image.png
两种方式对比:
显然点的方式更加简单,但这种方式只适用于要访问的属性名称是合法的标识符,并且需要知道要访问的属性名称。
如果属性名称是一个不合法标识符(如数字,空格或保留字等等),则必须用方括号。
如果属性名称是通过运算得出的值而不是固定的值的时候,则必须用方括号。

【属性继承】
image.png

【属性访问错误】
规则1:查询一个不存在的属性不会报错,只会返回undefined;
规则2:如果对象不存在,比如null或者undefined,那么试图查询这个不存在的对象的属性就会报错;
规则3:有一些属性是只读的,不能重新赋值,比如prototype;
image.png

【删除属性】
delete一元运算符,是用来删除对象属性或者数组元素,它的操作数是一个属性访问表达式。
语法:delete user.name; //user不再具有name属性
规则1:delete运算符只是断开和宿主的联系,不会去操作属性中的属性;
规则2:delete只能删除自身属性,不能删除继承属性(必须到原型中进行删除,并且这会影响到所有继承对象);
规则3:当删除成功、删除不存在属性、不是属性表达式等情况时,返回true;返回fasle的情况较少,一般也不会用到返回值;
规则4:删除数组元素后,数组长度不变,空的地方用undefined填充;

【检测属性】
检测属性是否存在对象,有如下方法:in运算符、hasOwnProperty() 和 propertyIsEnumerable()
in运算符:左侧是字符串形式的属性名,右侧是对象,如果对象的自有属性或继承属性中包含这个属性则返回true;
hasOwnProperty()方法:用来检测是否是对象自有属性,对于继承属性返回false;
propertyIsEnumerable()方法:是前者的加强版,只有属性是自有而且是可枚举的才返回true;
操作示例:
image.png

【枚举属性 - 遍历】
使用for/in循环可以遍历对象中所有_可枚举 _的属性(_包括自有和继承的 _),并把属性名称赋值给循环变量。
其中,对象继承的内置方法是不可枚举的,程序中添加的属性都是可枚举的。
除了for/in循环外,JS还提供了两个用以枚举属性名称的函数,keys()和getOwnPropertyNames()。
判断a对象的属性个数: Object.getOwnPropertyNames(a).length

//例1 -- 内置方法不可枚举,不会输出:
var o = {x:1,y:2,z:3,funX:function(){alert(1)}};
Object.prototype.m = 4; 
alert(o.propertyIsEnumerable("x"));   // true
alert(o.propertyIsEnumerable("toString")); // false
for(p in o) console.log(p);  // 输出x,y,z,funX,m

//例2 -- 跳过继承的属性和所有方法(接上例):
for(p in o){
	if(!o.hasOwnProperty(p)) continue;   // 跳过继承的属性
	if(typeof o[p]=== 'function') continue;   // 跳过方法
	console.log(p);    // 函数funX和继承的m跳过了
} 

keys和getOwnPropertyNames的区别
说明:返回对象自己(非原型继承的属性)的属性名称,包括函数。
方法:
Object.keys(object); // 返回一个由给定对象的所有_可枚举 _自身属性的属性名组成的数组。
Object.getOwnPropertyNames(object); // 类似keys,但是包括不可枚举的属性,即返回更多的属性。
参数:object,如果不是object类型,则引发TypeError异常。

【属性的setter和getter】
ECMAScript5中的对象存取器属性:getter和setter,存取器属性IE6、7、8不支持。
getter 是一种获得属性值的方法,setter是一种设置属性值的方法。巧用get和set,能够直接操作对象属性实现读写,可以极大的提高编程效率。
如何定义?有2种办法:在对象初始化的时候定义,在对象定义后的时候定义,见下面例子。

//demo1 -- 在对象初始化的时候定义
var obj = {
    val:100,
    get getval(){
        return this.val;
    },
    set setval(x){
        this.val = x;
    }
}
console.log(obj.getval);
obj.setval = 101;
console.log(obj.getval);
//demo2 -- 在对象定义后的时候定义
var obj2 = {
    val:200
}
obj2.__defineGetter__('name',function(){return this.val});
obj2.__defineSetter__('name',function(name){this.val = name;})
console.log(obj2.name)
obj2.name = 201; 
console.log(obj2.name);

规则1:setter和getter定义的属性称为“存取器属性”,它们不同于“数据属性”,“数据属性”只是一个简单的值;
规则2:set和get 方法不一定要同名,名字任意,也可以不仅仅简单返回一个属性的值,而是组合的复杂表达式;
规则3:set和get 方法也可以被继承;读取set属性的时候总返回undefined,set忽视返回值;
规则4:注意这里set和get方法的调用,并不像函数那样调用,调用get直接像属性那样,set是用赋值方式调用;
规则5:更多时候并不是简单的像例子那样,针对某个属性set和get,而是封装一些常用方法;

【属性的特性】
属性除了名字和值外,还有可写、可配置和可枚举的特性,本章节涉及的内容,IE6、7、8不支持。
一般认为数据属性具有值(value)、可写性(writable)、可枚举性(enumerable)和可配置性(configurable)这四个特性。
对于存取器属性来说,不具备值和可写性,增加了set和get特性。
通过调用getOwnPropertyDescriptor()可以获得某个对象的某个自有属性 的特性,要获取继承的属性,要通过getPrototypeOf()方法。
设置特性可以使用defineProperty()和defineProperties(),更详细的请参考书籍6.7。

//常用操作示例:
let o = {x:1,y:2,z:3,funX:function(){alert(1)}};
Object.prototype.m = 4;
Object.getOwnPropertyDescriptor(o,'x');  // 获得 Object {value: 1, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(o),'m')// 获得继承的属性m的特性
Object.defineProperty(o,"x",{value:2,writable:false});   //修改属性x的特性
Object.getOwnPropertyDescriptor(o,'x');  // 再次获取 Object {value: 2, writable: false, enumerable: true, configurable: true}

Object 常用方法

Object.create(prototype[,descriptors])
这个方法用于创建一个对象,并把其prototype属性赋值为第一个参数,同时可以设置多个descriptors,关于decriptor下一个方法就会介绍这里先不说。只需要这样就可以创建一个原型链干净对象了。

const o = Object.create({
    "say": function () {
        alert(this.name);
    },
    "name":"Byron"
});

Object.defineProperty(O,Prop,descriptor) / Object.defineProperties(O,descriptors)
想明白这两个函数必须明白descriptor是什么,在之前的JavaScript中对象字段是对象属性,是一个键值对,而在ECMAScript5中引入property,property有几个特征:

  1. value:值,默认是undefined
  2. writable:是否是只读property,默认是false,有点像C#中的const
  3. enumerable:是否可以被枚举(for in),默认false
  4. configurable:是否可以被删除,默认false
  5. get:返回property的值得方法,默认是undefined
  6. set:为property设置值的方法,默认是undefined
Object.defineProperty(o,'age', {
    value: 24, //值
    writable: true, //可写
    enumerable: true,  //可枚举
    configurable: true  //可删除
});

const a= {};
Object.defineProperty(a, "b", {
  set:function(newValue){
	  console.log("你要赋值给我,我的新值是"+newValue);
	},
  get:function(){
	  console.log("你取我的值");
	  return 2; //注意这里,我硬编码返回2
   }
})

Object.getOwnPropertyDescriptor(O,property)
这个方法用于获取defineProperty方法设置的property 特性

const props = Object.getOwnPropertyDescriptor(o, 'age');
console.log(props); //Object {value: 24, writable: true, enumerable: true, configurable: true}

Object.getOwnPropertyNames
获取所有的属性名(方法也是属性),不包括prototy中的属性,返回一个数组

console.log(Object.getOwnPropertyNames(o)); //["age", "sex"]

例子中可以看到prototype中的name属性没有获取到
说明:原型上的属性都不会获取到,如Object.create方法创建的属性都不会返回。

Object.keys()
和getOwnPropertyNames方法类似,但是获取所有的可枚举的属性,返回一个数组

console.log(Object.keys(o)); //["age"]

说明:即enumerable属性为true的才可以被查询到,正常通过点方式增加的属性都是可枚举的。

Object.preventExtensions(O) / Object.isExtensible
方法用于锁住对象属性,使其不能够拓展,也就是不能增加新的属性,但是属性的值仍然可以更改,也可以把属性删除,Object.isExtensible用于判断对象是否可以被拓展

Object.seal(O) / Object.isSealed
方法用于把对象密封,也就是让对象既不可以拓展也不可以删除属性(把每个属性的configurable设为false),单数属性值仍然可以修改,Object.isSealed由于判断对象是否被密封

Object.freeze(O) / Object.isFrozen
终极神器,完全冻结对象,在seal的基础上,属性值也不可以修改(每个属性的wirtable也被设为false)


总结陈词

本篇文章带大家认识一下JavaScript对象,更多JS知识,欢迎阅读《JS权威指南》等书籍。
JavaScript真的就挺强大的,可以多花一些时间去挖掘它,也让我们继续见证了 JavaScript 的博大精深,后续会更新更多内容。
💗 如果觉得内容还可以,麻烦点个关注不迷路,您的鼓励是我创作的动力。

CSDN_END.gif

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

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

相关文章

OpenStack Yoga版安装笔记(七)glance练习补充

1、练习场景说明 在OpenStack Yoga版安装笔记(五)中,glance已经在controller node虚拟机上安装完成,并且已经成功拍摄了快照。 此时,controller node虚机已经安装了keystone、keystone DB、glance、glance DB、OpenSta…

利用【MATLAB】和【Python】进行【图与网络模型】的高级应用与分析】

目录 一、图与网络的基本概念 1. 无向图与有向图 2. 简单图、完全图、赋权图 3. 顶点的度 4. 子图与连通性 5. 图的矩阵表示 MATLAB代码实例 Python代码实例 二、最短路径问题 1. 最短路径问题的定义 2. Dijkstra算法 MATLAB代码实例 Python代码实例 三、最小生…

昇思MindSpore学习总结十七 —— 基于MindSpore通过GPT实现情感分类

1、要求 2、导入了一些必要的库和模块 以便在使用MindSpore和MindNLP进行深度学习任务时能使用各种功能,比如数据集处理、模型训练、评估和回调功能。 import os # 导入操作系统相关功能的模块,如文件和目录操作import mindspore # 导入MindSpore库&a…

入门C语言只需一个星期(星期六)

点击上方"蓝字"关注我们 01、创建结构体 struct MyStructure { // 结构声明 int myNum; // 成员(int 变量) char myLetter; // 成员(char 变量)}; // 用分号结束结构创建一个名为 s1 的结构变量​struct myStru…

# Redis 入门到精通(九)-- 主从复制(1)

Redis 入门到精通(九)-- 主从复制(1) 一、redis 主从复制 – 主从复制简介 1、互联网“三高”架构 高并发高性能高可用 2、你的“Redis”是否高可用? 1)单机 redis 的风险与问题 问题1.机器故障  现…

kafka服务介绍

kafka 安装使用管理 Kafka Apache Kafka 是一个开源的分布式事件流平台,主要用于实时数据传输和流处理。它最初由 LinkedIn 开发,并在 2011 年成为 Apache 基金会的顶级项目。Kafka 设计的目标是处理大规模的数据流,同时提供高吞吐量、低延迟…

C语言 通讯录管理 完整代码

这份代码,是我从网上找的。目前是能运行。我正在读。有些不懂的地方,等下再记录下来。 有些地方的命名,还需要重新写一下。 比如: PersonInfo* info &address_book->all_address[address_book->size]; 应该改为: Perso…

C#实现数据采集系统-实现功能介绍

系统介绍 我们这里主要使用C#( .Net 6)来实现一个数据采集系统,从0到1搭建数据采集系统,从系统分析,功能拆解,到一一实现 数据采集 数据采集是企业信息化和数字化转型过程中的关键环节,它涉及到从生产设备、传感器…

Microsoft Visual C++ 2010 Express 使用

Microsoft Visual C 2010 Express 使用 Microsoft Visual C 2010 Express(简称VC 2010 Express)是一款免费的集成开发环境(IDE),专为C和C语言的开发者设计。 安装 下载|本站链接【VC2010简体中文版】的安装包并解压…

2024年新手卖家该如何做好亚马逊运营?

随着电子商务的蓬勃发展,越来越多的新手卖家选择在亚马逊这一国际电商巨头平台上开展业务。然而,想要在竞争激烈的市场中脱颖而出,新手卖家需要精心规划并执行有效的运营策略。以下是为2024年新手卖家提供的关于如何做好亚马逊运营的一些建议…

C#学习-刘铁猛

文章目录 1.委托委托的具体使用-魔板方法回调方法【好莱坞方法】:通过委托类型的参数,传入主调方法的被调用方法,主调方法可以根据自己的逻辑决定调用这个方法还是不调用这个方法。【演员只用接听电话,如果通过,导演会…

刷题笔记 739. 每日温度 (单调栈),215. 数组中的第K个最大元素(堆),347.前 K 个高频元素

739. 每日温度 (单调栈). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/daily-temperatures/description/?envTypestudy-plan-v2&envI…

Fast Planner规划算法(一)—— Fast Planner前端

本系列文章用于回顾学习记录Fast-Planner规划算法的相关内容,【本系列博客写于2023年9月,共包含四篇文章,现在进行补发第一篇,其余几篇文章将在近期补发】 一、Fast Planner前端 Fast Planner的轨迹规划部分一共分为三个模块&…

Haproxy服务

目录 一.haproxy介绍 1.主要特点和功能 2.haproxy 调度算法 3.haproxy 与nginx 和lvs的区别 二.安装 haproxy 服务 1. yum安装 2.第三方rpm 安装 3.编译安装haproxy 三.配置文件详解 1.官方地址配置文件官方帮助文档 2.HAProxy 的配置文件haproxy.cfg由两大部分组成&…

React+TypeScript 组件库开发全攻略:集成Storybook可视化与Jest测试,一键发布至npm

平时我除了业务需求,偶尔会投入到UI组件的开发中,大多数时候只会负责自己业务场景相关或者一小部分公共组件,极少有从创建项目、集成可视化、测试到发布的整个过程的操作,这篇文章就是记录组件开发全流程,UI组件在此仅…

RabbitMQ学习实践二:MQ的实现

文章是本人在学习springboot实现消息队列功能时所经历的过程的记录,仅供参考,如有侵权请随时指出。 参考文章地址: RabbitMQ安装与入门_rabbitmq win11配置-CSDN博客 RabbitMQ入门到实战一篇文章就够了-CSDN博客 RabbitMQ系列&#xff08…

AI跟踪报道第48期-新加坡内哥谈技术-本周AI新闻:Open AI 和 Mistral的小型模型

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

华为路由器SSH登录实验

概念 SSH全称安全外壳(Secure Shell)协议,这个协议的目的就是为了取代缺乏机密性保障的远程管理协议,SSH基于TCP协议的加密通道,让客户端使用服务器的RSA公钥来验证SSHv2服务器的身份。 创建密钥对 在充当SSH服务器的…

UE4-获得角色控制权的两种方法

方法一: 方法二: 注意此方法不能有多个玩家出生点,如果有多个玩家出生点,会随机的选择一个玩家出生点进行生成。

C++的map和set介绍

系列文章目录 二叉树搜索树 map和set习题 文章目录 系列文章目录前言一、关联式容器键值对二、树形结构的关联式容器2.1 set2.1.1 set的介绍2.1.3 set的使用删除节点find的不同效率count举例lower_bound 和 upper_bound 2.2 multiset2.2.1 区别:find查找erase删除e…