《HTML5+JavaScript动画基础》——2.4 JavaScript对象-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

《HTML5+JavaScript动画基础》——2.4 JavaScript对象

简介: 由于执行函数需要一些额外的计算,采用函数实现遍历的一个缺点就是其速度会慢于for循环。当开发者在编写程序时,经常需要同时考虑代码的可读性与执行速度,而这只能交由测试决定。通常情况,你应该尽可能编写简单易懂的程序,而让浏览器厂商去关心如何让代码执行得更快。

本节书摘来自异步社区《HTML5+JavaScript动画基础》一书中的第2章,第2.4节,作者:【美】Billy Lamberta , Keith Peters著,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.4 JavaScript对象

本书的重心在于使用JavaScript创建动画所需的各种原理和公式而不是具体的编程技巧。因此,本书中不会创建庞大的框架库或者复杂的数据结构,而是尽可能保持代码的简洁。

你可以将在本书中学到的动画概念纳入更加高级的JavaScript项目中,不过,本书的目的不是交给你一份预先构建好的代码供你复制和粘贴,而是试图让你理解每一种动画的工作原理。

由于本书采用JavaScript编写示例,因此你需要了解该语言的一些重要概念以便于理解示例代码。JavaScript中最重要的东西就是对象和函数(一种特殊的对象),让我们从它们入手吧。

2.4.1 基础对象
JavaScript被设计成一个简单的面向对象系统。对象是一个包含若干属性的数据结构。这些属性可以是变量、函数或其他对象。当给一个函数赋给一个属性时,它称为一个对象的方法。浏览器中预定义了很多对象,不过开发者也可以创建自定义的对象。例如,可以像下面这样创建一个空对象并将它赋给一个变量供将来引用:

var objA = {};
这里创建了一个不具备任何属性的对象并将其保存到变量objA中。由于JavaScript对象默认情况下可以在任何时间修改,因此可以像下面这样为它添加一个新的属性:

objA.name = "My Object A";
以上代码在objA对象中创建了一个名为name的新属性并把一个字符串值"My Object A"赋予它。总是可以通过objA.name的方式访问对象的属性值。也可以如下在声明一个新对象的时候就为之创建属性:

var objB = {
 name: "My Object B",
 hello: function (person) {
  console.log("Hello, " + person);
 }
};

这里创建一个新对象objB,它包含两个属性,一个包含字符串的name属性以及一个保存函数的hello属性。由于在JavaScript中函数也是对象,因此可以像对待其他值一样将其传来传去,也可以将其赋给某个变量。上面这个例子中的方法接收一个字符串参数,并向浏览器的调试控制台输出一条消息:

objB.hello("Gentle Reader"); //prints: "Hello, Gentle Reader"
2.4.2 创建一类新对象
可以声明对象使其包含所需的属性,不过如果你想要创建多个包含相同属性定义的对象,该怎么办呢?当然可以逐一创建它们,不过更加高效的方式是使用构造函数。构造函数是一种特别的函数,它会根据分配给它的属性创建新的对象。在定义好该函数后,可以使用new命令调用构造函数以创建新的对象。为了区分构造函数与普通函数,约定构造函数的名称首字母大写:

function MyObject (person) {
 this.name = person;
 this.say = function () {
  console.log("It's " + this.name);
 };
}
var objA = new MyObject("Gentle Reader");
objA.say(); //prints: "It's Gentle Reader"

留意,在构造函数中用于添加属性的特殊对象this。该对象将作为构造函数的返回值。在构造函数中声明的任何变量如果没有关联到this对象,则无法在构造函数外直接访问。

2.4.3 原型
使用构造函数创建对象实例是在基于类的语言中的习惯做法。事实上,当你查看JavaScript文件中对类的介绍时,你会发现它通常所指的就是构造函数。不过该术语有时候会让人忽略了JavaScript实际上是基于原型的语言。

当在JavaScript中创建新对象实例时,实际上创建新对象,该对象从其构造函数对象(即其原型对象)中继承它的所有属性。可以通过构造函数的prototype属性直接访问这些对象。赋予原型的任何属性都将被派生自该类型的所有对象所共享。以下代码基于之前的示例构造函数:

MyObject.prototype.hello = function () {
 console.log("Hello, " + this.name);
};
objA.hello(); //prints: "Hello, Gentle Reader"
var objB = new MyObject("Inspired Coder");
objB.hello(); //prints: "Hello, Inspired Coder"

这里为构造函数的原型对象添加了hello函数,这样做之后,把该函数同时添加到之前声明的objA对象以及新创建的objB对象中。

本书中创建了一些被很多示例共享的类(一个构造函数与prototype属性)。通常情况下,把这些类放入一个独立的文件然后导入HTML5文件中。

2.4.4 函数风格
JavaScript的一大优势在于函数是作为一等公民而存在的对象。这意味着,可以将函数赋予变量,将它们传来传去并将它们作为其他函数的参数,而这是很多编程语言所不具备的强大功能与概念。尽管它蕴含的内容可以演变得相当复杂,但是这个概念却非常简单明了,并且在本书大量运用。如果你能够很好地掌握这一概念,你将成为一个成功的JavaScript程序员。

你已经在之前创建一个动画循环的时候使用过函数参数,setInterval与requestAnimationFrame都有使用回调函数作为它们的参数。除此之外,还可以用函数简化代码。例如,下面用一个for循环遍历一个数组中的值。创建计数器变量i,它在每次循环中递增并用于访问数组的值。声明一个包含三个元素的数组并将它们轮流输出到控制台。

var arr = [1, 2, 3];
for (var i = 0, len = arr.length; i < len; i++) {
 console.log(arr[i]);
}

也可以用函数实现上述功能。每个JavaScript数组对象都有一个名为forEach的方法,该方法接收一个函数作为参数。forEach方法会遍历所有的数组元素,将每个元素作为第一个参数传递给用户定义的函数,同时该元素在数组中的索引位置会作为第二个可选参数传入。以下是采用该方法实现之前那个例子的代码:

var arr = [1, 2, 3];
arr.forEach(function (element, i) {
 console.log(element);
});

以上代码段跟之前的示例实现了相同的功能(将数组中的每个元素输出到控制台),不过结构却大不相同。这么做有以下几点好处。首先,不用为了遍历声明任何临时变量,尤其是这些变量在这段代码执行完后就没用了。不过更重要的在于,这种风格的代码使得你能够写出函数层面的代码。这意味着,可以通过查看作为参数传入的函数与函数接收的参数了解代码如何工作,而无须担心循环的状态或依赖的变量是否设置正确。这有利于调试,因为当发生错误时,可以通过一层层深入栈跟踪上的函数调用来定位发生错误的代码。

由于执行函数需要一些额外的计算,采用函数实现遍历的一个缺点就是其速度会慢于for循环。当开发者在编写程序时,经常需要同时考虑代码的可读性与执行速度,而这只能交由测试决定。通常情况,你应该尽可能编写简单易懂的程序,而让浏览器厂商去关心如何让代码执行得更快。

在本书中根据速度和简洁性的不同需求,两种遍历方式都有用到。使用JavaScript与DOM更常见也更核心的用法也需要将函数作为事件处理程序传入。我们会在下一节介绍用户交互时了解这是如何工作的。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章
最新文章
相关文章