搜索
首页web前端js教程JavaScript中对象属性详解

JavaScript中对象属性详解

Nov 28, 2019 pm 05:37 PM
js对象属性

JavaScript中对象属性详解

JavaScript 中的对象概念的确很容易让人困惑。看下面一个例子:

var strPrimitive = "I'm mamacat";
typeof strPrimitive; // "string"
strPrimitive instanceof String; // false

var strObject = new String("I'm mamacat");
typeof strObject; // "object"
strObject instanceof String; // true

strPrimitive.substr(8, 3); // "cat"

同样的字符串赋值到对象,一会儿是字符串类型一会儿是对象,而明明不是对象类型的变量还是可以使用对象属性,为什么会这样呢?

【相关课程推荐:JavaScript视频教程】  

类型和内置对象

JavaScript 中一共有六种主要(语言)类型,即 string, number, boolean, null, undefined 和 object,其中前五个基本类型都不是对象(对 null 进行 typeof 得到的是 "object",这是语言本身的 BUG)。而在此之外,则有许多特殊的对象子类型,例如数组、函数和内置对象等。

有些内置对象的名字看着和简单基本类型一样,就比如 String,Boolean,Object 之类。这些内置对象从表现形式看就和别的面向对象语言中的“类”概念差不多,而正如上篇文章所属,它们实际使只是一些能被用来构造一个对应子类型的内置函数而已(不要困惑,函数也是对象,这里并不矛盾)。于是就可以回到最初的例子,strObject 是由内置函数/内置对象 String 所构造的变量,对应 String 子类型,所以它是一个对象,而 strPrimitive 则是一个原始字面值而已。

当然,上面例子中最下面我们看上去对 strPrimitive 调用了 substr() 函数,这里则是因为,JavaScript 引擎会在需要时,把原始字面量转换成对应的对象,而转换之后我们自然就可以使用属性访问对应的方法了。

对象属性

那么,就上方的例子而言,String 对象实例就会有 substr() 函数可以用,但根据之前的文章可以知道,这些“函数”本身并不属于某个对象,而这些函数实质是对应对象的一个属性。当然,即便我们说某种类型的对象本身具备各种属性,实际上这些属性也多是各自独立存在的,只不过以引用的形式关联在了一起而已,这和之前了解的内容也并不矛盾。这些被关联起来的东西,被称为对象的 属性。

对象的复制

插播一条快报,尽管之前的文章提到过,上方也又一次反复强调过属性只是以引用的形式关联起来的独立存在,我们有时仍然会“理所应当”的认为属性是对象的一部分,而最容易因此踩坑的地方之一就是对象的复制了。仔细思考即可知道,当我们复制对象时,由于其属性本身只是引用关联,故“复制”得到的对象所包含的属性引用指向的和原本对象的属性引用其实还是同一个位置:

var ori = { a : 1};
var ori_copy = ori;
ori.a = 61;
ori_copy.a; // 61

显然这很可能和我们的期望不一样,而我们想要真正的拷贝对象则没有完美适用性的方案,很多时候的常规做法则是把对象序列化一下,然后再以此反序列化得到新的对象来实现对象的拷贝(比如使用 json)。ES6 中新增了 Object.assign() 来进行对象的浅拷贝,做法是把对象的所有可枚举属性等号赋值到新对象中。不过仍需注意的是,等号赋值并不会赋值属性的元信息(属性描述符,后述),在需要的情况下应当特别留意。

属性访问和数组

访问对象所关联的属性的方式即通过 . 或者 [] 操作符进行访问,obj.a 和 obj["a"] 访问的属性实质上是一样的,而这两种访问形式的区别也只有访问的属性名称里能不能有奇怪的符号而已。[] 操作符内扔的是个字符串,实际上属性名也永远都是字符串。当然,这个概念可能比较意外的就是,数组的下标访问其实并不是例外,数字还是被转换成了字符串才被使用的。

// 对象的属性访问:
var tejilang = {1 : "Teji Wolf"};
tejilang instanceof Array; // false
tejilang["1"]; // "Teji Wolf"
tejilang[1]; // "Teji Wolf"

// 这回保证它是 Array
var macat = ["codingcat"];
macat instanceof Array; // true
macat.length; // 1
macat[0]; // "codingcat"
macat["0"]; // "codingcat"
macat.length = 20;
macat; // (20) ["codingcat", empty × 19]

数组下标既然不属例外情况,那数组对象必然有其它属性控制数组本身的行为,例如上例中,macat 数组的长度就是 length 属性所体现的,通过修改它的值也就改变了对象本身对外的表现形式。当然,由于数组本身就是对象,所以我们还是可以把数组当键值对来用,只是这种做法通常是没有意义且会让人感到困惑的。JavaScript 引擎通常都根据对象的类型做了不同程度的优化,故除了代码逻辑可读性外,合理的使用也是多少可以改善性能的。

能够通过字符访问属性还是存在一些别的好处的,比如 ES6 的可计算属性名。当然 ES6 不在本文的关注范围内,所以这里就不再讨论了。

属性描述符

有时我们可能不希望某个属性被随意修改,有时候我们需要额外配置一些属性的信息,自 ES5 起,所有的属性就都具备了“属性描述符”(Property Descriptor)来控制属性本身的这些元信息。

数据描述符

来看这个例子:

var chris = {};
Object.defineProperty(chris, "IQ", {
    value: 228,
    writable: false,
    configurable: true,
    enumerable: true
});
chris.IQ = 61; // 静默失败了,如果是严格模式则会 TypeError
chris.IQ; // 228

通过 defineProperty 可以对一个对象的属性配置其对应的属性描述符(元信息),而属性描述符则包含访问描述符和数据描述符,上面的例子中,defineProperty 的第三个参数就定义了数据的若干数据描述符,其中 writable 表示可写,configurable 表示属性是否可配置(注意,修改成不可配置是单向操作),enumerable 则表示属性是否应当出现在枚举中,比如 for..in 中。

显然我们可以通过属性描述符实现对属性的保护,而同时也存在一些方便函数来做近似的事。如 Object.preventExtensions() 会保留原有属性但禁止添加新属性,Object.seal() 会密封对象,在禁止添加新属性的基础上把原有属性标记为不可配置,Object.freeze() 会冻结对象,即在密封的基础上把数据访问属性标记为不可写。

[[Get]], [[Put]] 和访问描述符

在我们访问和赋值一个对象的属性时,实际上是通过 [[Get]] 和 [[Put]] 操作进行的,例如属性访问时,[[Get]] 会先找有没有这个属性,如果没有则会遍历对象的 [[Prototype]] 链(原型链,这次不谈这个概念)来找,实在找不到则返回 undefined 。而这个行为实际是允许我们通过设置 getter (get())和 setter (set())函数来改变的,它们被称为 访问描述符。

当我们提供访问描述符时,对应的访问操作就不再受到 value writable 属性的影响了,另外需要注意的是,尽管它们也是属性描述符,但定义 getter 和 setter 并不要求一定要通过 defineProperty 设置:

var obj = {
    get a() { // 给 a 属性定义 getter
        return this._a_;
    },
    set a(val) { // a 属性的 setter
        this._a_ = val * 2;
    }
}

obj.a = 2;
obj.a; // 4

属性存在性

因为属性的值也可能是 undefined,不存在的属性直接访问得到的也是 undefined,所以直接通过简单的属性访问是无法区分是否存在的,这时我们即可通过 in 或者 hasOwnProperty() 检查属性是否存在对象中了:

var obj = {a : 2};
"a" in obj; // true
obj.hasOwnProperty("a"); // true

尽管仍没有讲到原型链的概念,这里仍然应注意,in 操作符会检查原型链中是否存在属性,而 hasOwnProperty 则不会。另外在一些情况下,有的对象会没有 hasOwnProperty 这个属性(此处不提原因),这时可以用过 Object.prototype.hasOwnProperty.call(objName, propertyName) 来实现检查。

本文来自 js教程 栏目,欢迎学习!  

以上是JavaScript中对象属性详解的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:博客园。如有侵权,请联系admin@php.cn删除
Python vs. JavaScript:社区,图书馆和资源Python vs. JavaScript:社区,图书馆和资源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

从C/C到JavaScript:所有工作方式从C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript引擎:比较实施JavaScript引擎:比较实施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

超越浏览器:现实世界中的JavaScript超越浏览器:现实世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

使用Next.js(后端集成)构建多租户SaaS应用程序使用Next.js(后端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

如何使用Next.js(前端集成)构建多租户SaaS应用程序如何使用Next.js(前端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript:探索网络语言的多功能性JavaScript:探索网络语言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的演变:当前的趋势和未来前景JavaScript的演变:当前的趋势和未来前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器