资讯专栏INFORMATION COLUMN

JS语言精粹--对象

20171112 / 1520人阅读

摘要:属性值可以从包括另一个对象字面量在内的任意表达式中获得,而对象是可嵌套的。所有通过字面量创建的对象,都连接到这个中的标准的对象。

这篇文章算是我职业生涯中的第一篇技术博文吧,有些地方可能表达得不是很好,还望大家多多包涵哈^_^!

正文

JavaScript的简单类型有数字、字符串、布尔值(true、false)、null值和underfind值,其他所有的值都是对象。

数字、字符串和布尔值“貌似”是对象,因为它们都拥有方法,但是它们是不可变的。而JavaScript中的对象是可控的键控集合

在JavaScript中,数组是对象,函数是对象,正则表达式是对象,当然,对象自然也是对象。

对象是属性的容器,其中每个属性都拥有名字和值(name-value)。属性名可以是包括字符串在内的任意字符串,属性值可以是除undefined值之外的任意值。

JavaScript中的对象是无类别(class-free)的,它对新属性的名字和值没有约束。对象适合用于收集和管理数据。对象可以包含其他对象,所以它们可以容易的表示成树形或图形结构。

JavaScript包括一个原型链特性(这是JS对象中很重要的一个特性,具体用法以后我会发一篇针对原型链及其用法的文章进行专门说明),允许对象继承另一个对象的属性,正确地使用它能减少对象初始化的时间和内存耗损。

1. 对象字面量

对象字面量,提供了一种非常方便的创建新对象值得表示法,即包围在一对花括号中的零个或多个“名/值”对(也称为键值对),它可以出现在任何允许表达式出现的地方。

javascriptvar empty_object = {};
var batman = {
    "first-name": "Bruce",
    "last-name": "Wayne"
};

属性名可以是包括空字符串在内的任何字符串,不过,一个合法的变量标识符,不能是保留字,虽然不强调用引号括住,但是,像“first-name”、“first name”这类含有“-”或是空格的属性名,是必须加上引号括住的。逗号用来分隔多个“名/值”对。

属性值可以从包括另一个对象字面量在内的任意表达式中获得,而对象是可嵌套的。

javascriptvar flight = {
    airline: "Domestic",
    number: 1024,
    departure: {
        IATA: "SZ",
        time: "2015-08-03 15:00:00",
        city: "shenzhen"
    },
    arrival: {
        IATA: "BJ",
        time: "2015-08-04 00:00:00",
        city: "beijing"
    }
};
2. 检索

要检索对象中包含的值(或属性值或方法或其它),可以采用在 [] 后缀中括住一个字符串表达式的方式,如果字符串表达式是一个合法js标识符且不为保留字的常数,那么优先考虑用 . 表示法,因为它更紧凑且可读性更好。

javascriptbatman["first-name"]    // "Bruce"
flight.departure.city   // "shenzhen"

如果你尝试检索一个并不存在的成员元素的值(这里的属性表达式是严格区分大小写的),将返回一个undefined值。

javascriptbatman["middle-name"]   // undefined
flight.status           // undefined
batman["FIRST-NAME"]    // undefined

|| 运算符可以用来填充默认值:

javascriptvar middle = batman["middle-name"] || "(none)";
var status = flight.status || "unknown";

尝试检索一个undefined值将会导致TypeError异常,这可以通过 && 运算符来避免错误。

javascriptflight.equipment                             // undefined
flight.equipment.model                       // throw "TypeError"
flight.equipment && flight.equipment.model   // undefined
3. 更新

对象中的值可以通过赋值语句来更新。

如果属性名已经存在于对象中,那么这个属性值将被替换。

javascriptbatman["first-name"] = "Damian";

如果对象之前并没有这个属性名,那么该属性将会被扩充到该对象中。

javascriptbatman["middle-name"] = "AI";
batman["nickname"] = "Robin";
flight.equipment = {
    model: "Boeing 777"
};
flight.status = "overdue";
4. 引用

对象通过引用来传递,它们永远不会被拷贝。

javascriptvar x = batman;
x.nickname = "Joker";
var nick = batman.nickname;  // 因为x和batman是指向同一个对象的引用,所以nick为"Joker"
var a = {},b = {},c = {};    // a、b、c 每个都分别引用一个不同的空对象
a = b = c = {};              // a、b、c 都引用一个相同的空对象
5. 原型

每个对象都会连接到一个原型对象,并且它可以从中继承属性。所有通过字面量创建的对象,都连接到 Object.prototype 这个JS中的标准的对象。

当创建一个新对象时,可以选择某个对象作为它的原型,给Object增加一个beget方法,这个beget方法创建一个使用原对象作为其原型的新对象,这个我们以后会在专门的博文做详细了解。

javascriptif(typeof Object.beget !== "function"){
    Object.beget = function(o){
        var F = function(){};
        F.prototype = o;
        return new F();
    };
};

var next_batman = Object.beget(batman);

原型连接在更新时是不起作用的,当我们对某个对象做出改变时,不会触及到该对象的原型:

javascriptnext_batman["first-name"] = "Damian55";
next_batman["middle-name"] = "Ai22";
next_batman.nickname = "Robin5";

原型连接只有在检索值的时候才会被用到。如果我们尝试去获取对象的某个属性值,且该对象没有该属性名,那么,JS会试着从原型对象中获取属性值,如果那个原型对象也没有该属性,则再从它的原型中寻找,以此类推,直到最后到达终点Object.prototype,若想要的属性完全不存在于原型链中,则返回undefined值,这个过程称为委托

原型关系是一种动态的关系,如果我们在原型中添加一个新的属性,该属性会立即对所有基于该原型创建的对象可见。

javascriptbatman.profession = "JSL";
next_batman.profession;      // "JSL"
6. 反射

检查对象并确认对象有什么属性,可以去检索该属性并验证取得的值。而确定属性的类型,可以使用typeof操作符。

javascripttypeof flight.number        // "number"
typeof flight.status        // "string"
typeof flight.arrival       // "object"
typeof flight.manifast      // "undefined"

请务必注意原型链中的任何属性也会产生一个值:

javascripttypeof flight.toString      // "function"
typeof flight.constructor   // "function"

有两种方法去处理这些不需要的属性:

让你的程序检查并剔除函数值,一般来说,做反射的目标是数据,因此其中一些值可能会是函数。

使用hasOwnProperty方法,如果对象拥有独立属性,它将返回true。

另外,hasOwnProperty方法不会检查原型链。

javascriptflight.hasOwnProperty("number");        // true
flight.hasOwnProperty("constructor");   // false
7. 枚举

for in 语句可用来遍历一个对象中的所有属性名,当然,也包括函数和我们可能不关心的原型中的属性,所以我们有必要过滤掉不必要的值。
最常用的过滤器(即过滤原型中的属性)是hasOwnProperty方法,以及使用typeof来排除函数:

javascriptvar name;
for(name in next_batman){
    if(typeof next_batman[name] !== "function"){
        document.writeln(name + ": " + next_batman[name]);
    }
}

以上,属性名出现的顺序是不确定的,因此要想确保属性以特定的顺序出现,最好是完全避免使用 for in 语句,而是创建一个数组,在其中以正确的顺序包含属性名:

javascriptvar i;
var properties = ["first-name","middle-name","last-name","profession"];
for(i = 0;i < properties.length;i ++){
    document.writeln(properties[i] + ": " + next_batman[properties[i]]);
}

通过使用普通for而不是for in ,可以得到我们想要的属性,而不用担心可能发掘出原型链中的属性,并按正确的顺序取得它们的值。

8. 删除

delete运算符可以用来删除对象的属性,它将会移除该对象的确定包含的属性,它不会触及原型链中的任何对象。

删除对象的属性可能会让来自原型链中的属性浮现出来。

javascriptnext_batman.nickname        // "Robin5"
// 删除next_batman的nickname属性,从而暴露出原型的nickname的属性值
delete next_batman.nickname; 
next_batman.nickname;       // "Robin"
9. 减少全局变量污染

JS可以随意定义可保存所有应用资源的全局变量,不幸的是,全局变量会削弱程序的灵活性,所以应该避免。

最小化使用全局变量的一个方法是在你的应用中只创建唯一一个全局变量:

javascriptvar MyApp = {};

该变量此时变成了你的应用容器:

javascriptMyApp.batman = {
    "first-name": "Bruce",
    "last-name": "Wayne"
};

MyApp.flight = {
    airline: "Domestic",
    number: 1024,
    departure: {
        IATA: "SZ",
        time: "2015-08-03 15:00:00",
        city: "shenzhen"
    },
    arrival: {
        IATA: "BJ",
        time: "2015-08-04 00:00:00",
        city: "beijing"
    }
};

只要把多个全局变量都整理在同一个命名空间下,你将显著降低与其他应用程序、组件或类库之间产生糟糕的相互影响(即耦合度高)的可能性,也使其变得更容易阅读,因为MyApp.batman指向的时顶层结构。当然,也可以使用闭包来进行信息隐藏,它是另一种有效减少全局污染的方法。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85843.html

相关文章

  • 《javascript语言精粹》学习笔记 - 继承

    摘要:但采用构造器调用模式,即是使用了前缀去调用一个函数时,函数执行的方式会改变。对象包含构造器需要构造一个新的实例的所有信息。构造器的变量和内部函数变成了该实例的私有成员。 JavaScript 是一门弱类型语言,从不需要类型转换。对象继承关系变得无关紧要。对于一个对象来说重要的时它能够做什么,而不是它从哪里来。 阅读《javascript语言精粹》笔记! 伪类 js的原型存...

    harriszh 评论0 收藏0
  • 【阅读笔记】JavaScript语言精粹

    摘要:对之前看高级程序设计时没有注意到的一些知识点,结合本书做以补充语法注释源于的型既可以出现在字符串字面量中,也可能出现在正则表达式字面量中,如故一般建议使用型注释保留字语句变量参数属性名运算符和标记等标识符不允许使用保留字,此外在对象字面量中 对之前看《JavaScript高级程序设计》时没有注意到的一些知识点,结合本书做以补充 语法 注释 源于PL/I的/* */型既可以出现在字符串字...

    cucumber 评论0 收藏0
  • 【阅读笔记】javascript 语言精粹

    摘要:前言由于最近的项目用到了一些的代码,所以我带着好奇心,认真阅读了这本书,粗略地了解语言的基本结构和特性,对于一些不熟悉的新概念,以记录的形式加强印象,也是对学习的反思总结。 前言 由于最近的项目用到了一些js的代码,所以我带着好奇心,认真阅读了这本书,粗略地了解js语言的基本结构和特性,对于一些不熟悉的新概念,以记录的形式加强印象,也是对学习的反思总结。 一、字面量(literals...

    tangr206 评论0 收藏0
  • 《javascript语言精粹》学习笔记 - 对象

    摘要:对象适用于汇集和管理数据。一个对象字面量就是包围在一对花括号的多个名值对。尝试从对象里取值将会导致异常。亦不会触及原型链中的任何对象。严格模式下,不能用删除显式声明的标识符,名称或具名函数。 Javascirpt里的对象是无类型的。它对新属性的名字和属性的值没有任何的限制。对象适用于汇集和管理数据。对象可以包括其他对象,所以它们可以容易地表示成树状或者图形结构。 对象字面量 ...

    LoftySoul 评论0 收藏0
  • 前端—初级阶段4(13-15)—JavaScript语言精粹

    摘要:调用函数时,被绑定到全局对象。如果使用构造器调用有前缀,且返回不是一个对象,则返回该新对象。闭包会导致原有作用域链不释放,造成内存泄漏。当采用构造器调用模式,函数执行的方式会被修改。 内容 ECMAScript核心语法结构:1.语法2.对象3.函数4.继承5.数组6.正则表达式7.方法8.附录A-毒瘤9.附录B-糟粕 一、语法 1.类型、值和变量 1) 类型:区分数据类型 在JS中使...

    iflove 评论0 收藏0
  • 前端—初级阶段4(13-15)—JavaScript语言精粹

    摘要:调用函数时,被绑定到全局对象。如果使用构造器调用有前缀,且返回不是一个对象,则返回该新对象。闭包会导致原有作用域链不释放,造成内存泄漏。当采用构造器调用模式,函数执行的方式会被修改。 内容 ECMAScript核心语法结构:1.语法2.对象3.函数4.继承5.数组6.正则表达式7.方法8.附录A-毒瘤9.附录B-糟粕 一、语法 1.类型、值和变量 1) 类型:区分数据类型 在JS中使...

    Wuv1Up 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<