《Eloquent JavaScript》笔记--对象与数组

数组

数组:用来存储连续的值。形式是方括号包围,用逗号分隔。

var listOfNumbers = [2, 3, 5, 7, 11];
console.log(listOfNumbers[1]);
// → 3
console.log(listOfNumbers[1 - 1]);
// → 2

取得数组中的值的方法是:数组名接方括号,里面是表达式,计算结果作为数组的索引。数组的索引从0开始。

属性

通过 值名.属性名可获得值的属性,如myString.length。几乎所有javascript值都有属性,除了null和undefined这2个属性。如果试图获取这2个逗比的属性,将会出错。

null.length;
// → TypeError: Cannot read property 'length' of null

javascript获得一个值的属性有2种方式,一种是句点.一种是方括号,如value.x和value[x]
但这2种方式不一定获得就是同一个属性。具体要看x是如何解析的。使用句点,后面的属性名必须是一个合法的变量名,它是直接作为属性的名字而存在的。使用方括号,方括号内的表达式先要被计算,结算的结果作为属性的名字。

数组的属性名(也就是索引)都是数字,所以我们必须使用方括号来获得数组的属性。
然而数组的length属性是一个合法的变量名,我们当然可以用string["length"],只是没有string.length方便。

方法

对象的属性如果是函数,这个函数此时叫做对象的方法。

var doh = "Doh";
console.log(typeof doh.toUpperCase);
// → function
console.log(doh.toUpperCase());
// → DOH

这个例子演示了数组对象的方法:

var mack = [];
mack.push("Mack");
mack.push("the", "Knife");
console.log(mack);
// → ["Mack", "the", "Knife"]
console.log(mack.join(" "));
// → Mack the Knife
console.log(mack.pop());
// → Knife
console.log(mack);
// → ["Mack", "the"]

对象

对象的值是一系列的属性的集合。

var day1 = {
  squirrel: false,
  events: ["work", "touched tree", "pizza", "running",
           "television"]
};
console.log(day1.squirrel);
// → false
console.log(day1.wolf);
// → undefined
day1.wolf = false;
console.log(day1.wolf);
// → false

属性的名如果不是合法的变量名字,或者合法的数字,必须用引号括上。

var descriptions = {
  work: "Went to work",
  "touched tree": "Touched a tree"
};

由此可见,花括号在javascript中有2种用途,一种用在语句的开头,表示一个代码块;一种表示对象。

读取不存在的属性将导致undefined。
可以对属性表达式使用赋值操作符=,这会对属性重新赋值,或者创建新的属性(原先没有这个属性)。

delete操作符会删除一个对象的属性,这不是一个常见操作。

var anObject = {left: 1, right: 2};
console.log(anObject.left);
// → 1
delete anObject.left;
console.log(anObject.left);
// → undefined
console.log("left" in anObject);
// → false
console.log("right" in anObject);
// → true

二元操作符in,会返回布尔值来表明对象是否有对应的属性。
关于设置一个属性为undefined和删除一个属性的区别是,前者是对象仍然有该属性(只是它的值变成了undefined),后者是对象没有了该属性,感觉像废话吧。in会返回false。

数组是一种特殊的对象,它专门存储一系列相关的值。

var journal = [
  {events: ["work", "touched tree", "pizza",
            "running", "television"],
   squirrel: false},
  {events: ["work", "ice cream", "cauliflower",
            "lasagna", "touched tree", "brushed teeth"],
   squirrel: false},
  {events: ["weekend", "cycling", "break",
            "peanuts", "beer"],
   squirrel: true},
  /* and so on... */
];

可变性

在javascript中,数值,字符,布尔型的值是不可变的(immutable),对象的值是可变的。你可以拼接或者截取字符串产生新的值,但是无法改变一个现有的值。
对象的值可以通过它的属性来修改。
对于数值型的值来说,120和120我们认为是相同的,不管他们在内存中是不是同一块bits。但是对象,“同一个对象的2个引用”和“2个对象包含了相同的属性”是完全的两码事。

var object1 = {value: 10};
var object2 = object1;
var object3 = {value: 10};

console.log(object1 == object2);
// → true
console.log(object1 == object3);
// → false

object1.value = 15;
console.log(object2.value);
// → 15
console.log(object3.value);
// → 10

object1和object2“抓住”的是同一个对象,object3是另一个对象,他的值正好同object1相等。
当使用“==”比较javascript对象时,只有当对象(引用)的值是属于同一个对象时,才返回true,如果是2个对象时返回false,即使2个对象的值相等。

对象的映射(map)

对象的映射是创建两个相关联的键/值的好办法,如下event和phi。

var map = {};
function storePhi(event, phi) {
  map[event] = phi;
}

storePhi("pizza", 0.069);
storePhi("touched tree", -0.081);
console.log("pizza" in map);
// → true
console.log(map["touched tree"]);
// → -0.081

可以使用for in可以遍历枚举型值,如数组和对象,每次迭代变量保存了值的属性或者索引。通过
name[var]的方式可以得到属性的值,或者数组的元素。

for (var event in map)
  console.log("The correlation for '" + event + "' is " + map[event]);
// → The correlation for 'pizza' is 0.069
// → The correlation for 'touched tree' is -0.081

关于数组

pop和push在数组末尾增加或删除数据,shift和unshift在数组头部增加或删除数据。

var todoList = [];
function rememberTo(task) {
  todoList.push(task);
}
function whatIsNext() {
  return todoList.shift();
}
function urgentlyRememberTo(task) {
  todoList.unshift(task);
}

indexOf方法有一个兄弟,lastIndexof,它从后往前寻找给定的元素。

var todoList = [];
function rememberTo(task) {
  todoList.push(task);
}
function whatIsNext() {
  return todoList.shift();
}
function urgentlyRememberTo(task) {
  todoList.unshift(task);
}

concat方法与“+”类似,合并数组,slice方法可返回数组一部分。

function remove(array, index) {
  return array.slice(0, index)
    .concat(array.slice(index + 1));
}
console.log(remove(["a", "b", "c", "d", "e"], 2));
// → ["a", "b", "d", "e"]

字符串与属性

字符串有indexOf和slice,与数组的方法类似。

console.log("coconuts".slice(4, 7));
// → nut
console.log("coconut".indexOf("u"));
// → 5

字符串的indexOf可返回多个字符,数组只能返回单个元素。

console.log("one two three".indexOf("ee"));
// → 11

trim可以删除字符串两端的空白,只想删除一边的,可以用trimLeft,trimRight。

console.log("  okay \n ".trim());
// → okay
console.log("|" + " a ".trimLeft() + "|");
// → |a |

取得字符串长度可以用length,返回特定位置的字符串用charAt,也可用字符串的数值属性。

var string = "abc";
console.log(string.length);
// → 3
console.log(string.charAt(0));
// → a
console.log(string[1]);
// → b

参数对象

当一个函数被调用时,一个叫arguments的特殊变量被加到函数体的运行环境当中,它引用一个对象,该对象包含所有传给函数的参数。

这个对象有length属性,保存了实际传入参数的数量,还有一系列的0,1,2,3...属性,分别对应一个参数。
它很像数组,但是不包含任何数组的方法。

function argumentCounter() {
  console.log("You gave me", arguments.length, "arguments.");
}
argumentCounter("Straw man", "Tautology", "Ad hominem");
// → You gave me 3 arguments.

使用一个loop循环,可以让函数接收任意数量的参数。

function addEntry(squirrel) {
  var entry = {events: [], squirrel: squirrel};
  for (var i = 1; i < arguments.length; i++)
    entry.events.push(arguments[i]);
  journal.push(entry);
}
addEntry(true, "work", "touched tree", "pizza",
         "running", "television");

上面这个函数正常接收第一个参数,然后通过循环接收剩余的参数,循环从1开始可跳过第一个参数。

Math对象

math对象本身几乎没用,它只是提供了一个命名空间。Math对象包含一些有用的方法,比如随机数生成方法:

function randomPointOnCircle(radius) {
  var angle = Math.random() * 2 * Math.PI;
  return {x: radius * Math.cos(angle),
          y: radius * Math.sin(angle)};
}
console.log(randomPointOnCircle(2));
// → {x: 0.3667, y: 1.966}

如果想要整数型随机数可以使用Math.floor (向下取整)。

console.log(Math.floor(Math.random() * 10));
// → 2

还有Math.ceil(向上取整)和Math.round(最接近的整数)2个类似的方法。

全局对象

所有的全局变量都属于全局对象,在浏览器中,全局对象存储在window对象中。

var myVar = 10;
console.log("myVar" in window);
// → true
console.log(window.myVar);
// → 10

总结

所有的值都有属性,除了null和undefined两个特别的。
对象可以实现键/值映射(map),使用for in可以遍历。
最后

本章有一个很复杂,对我来说很复杂的计算“相关性”的例子,我实在没有兴致钻进数学的汪洋大海中去,没有细致的看那个例子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值