1.1 值
JavaScript里有6种基本类型的值: number、string、Boolean、object、function和undefined.
1.3.2 prompt和confirm
浏览器提供的标准环境包含了更多用于弹出窗口的函数,可以使用confirm函数让用户选择OK/Cancel问题。该函数返回布尔值:如果用户单击OK,则返回true;如果单击Cancel,则返回false。
prompt函数可用于询问一个开放式问题,第一个参数就是该问题;第二个参数是用户需要输入文本的开头部分,可以在对话窗口里输入一行文本,该函数会将其返回作为一个字符串。
1.4 程序结构
Number函数将用户输入的值转化为数字。类似的函数还有String和Boolean
2.1.5 函数值
正如在前一章中提到的,JavaScript里的所有东西都是值,包括function函数。这就是说定义的函数名称可以像普通变量一样使用,而且其内容可以传递给表达式并用于更大的表达式。在下面的示例中,如果a不是false值,程序会调用变量a里的函数;而如果a为false值,代码则调用b函数。
var a = null;function b() { return "B"; }(a || b)();
(a || b)()这个看起来有点怪异的表达式将"调用时不传参数"的操作符()应用到(a || b)上,如果该表达式产生的不是函数,则调用会产生错误。一旦产生的是函数,就会像该例中那样,结果值被调用了。
如果仅需要一个未命名的函数值,function关键字可以用作一个表达式,就像这样:
var a = null;(a || function(){ return "B"; })();
匿名表达式function(){return "B";}仅创建了一个函数值。
2.2.3 递归
很多开发人员的基本原则是,只有在证明程序运行太慢时才去关注效率问题。一旦出现这种情况,找出占用时间最多的代码,然后将这些美观的代码改成高效的代码。
3.2 基本数据结构
对象的属性可以自由添加、删除及修改。对象所扮演的主要角色,实际上就是一个属性和对象的集合。
var cat = { color: "gray", name: "Spot", size: 46};
属性名如果不是一个合法的变量名称,则不可以用点标记法访问,只能使用中括号的形式访问。
in操作符用于判断某个名字是否存在于集合内。
比较对象时,JavaScript中的==操作符只有在赋予的两个值完全相同时才能返回true。比较两个内容相同的不同的对象将返回false;(对象==指针??)
数组可以使用中括号([])来创建: var mailArchive = ["mail one", "mail two", "mail three"];
join()方法将字符串数组转换为字符串,传入的参数用于将数组的各个值连接起来。
3.3 解决关于Emily姨妈家猫的问题
split()方法将一个字符串分解成一个数组,以给定的字符串作为参数来确定在什么位置分解字符串。
slice()方法用于从第一个参数所在的位置开始到第二个参数所在的位置结束拷贝出一部分字符串。
charAt()方法用于从某个字符串获取指定位置的字符。
indexOf()方法可以找出字符第一次出现的位置或者截取字符串中的子串。
3.3.6 日期表示
月份数字是从0到11;
getFullYear(), getMonth(), getDate(), getMinutes(), getSeconds(), getDay(), getTime();
测试两个日期对象是否相等可以使用如下代码:
var wende1 = new Date(1989, 10, 9), wende2 = new Date(1989, 10, 9); wende1.getTime() == wende2.getTime();
4.2.2 异常
throw是引发异常的关键字。关键字try用于设立异常障碍:如果代码块里的代码引发异常,catch代码块将会执行,在执行的时候,catch后面的变量将拥有该异常值。
异常的优点:只有在错误的发生点以及处理错误的点上才需要错误处理代码。两者中间的函数可以忽略这些。
try语句后面也可以跟finally关键字,意思是:不管发生什么,尝试运行try块的代码以后就运行这些代码。如果函数需要清除一些东西,清除代码通常应放在finally块里。
function forEach(array, action) { for (var i=0; i
操作其它函数的函数称为高阶函数。
5.2.1 修改函数
另一个很有用的高阶函数类型修改了传入的函数值:
function negate(func) { return function(x) { return !func(x); };}var isNotNaN = negate(isNaN);
5.2.2 规约函数
sum函数实际上是算法的一个变体,该算法通常称为规约(reduce):
function reduce(combine, base, array) { forEach(array, function(element){ base = combine(base, element); }); return base;}function add(a, b) { return a+b;}function sum(numbers) { return reduce(add, 0, numbers);}
5.2.3 映射数组
另外一个与数组有关的"基本算法"称为映射(map)。它能够遍历数组,并且将函数应用于每个元素。但是它不会丢弃函数返回值,而是利用这些返回值重新建立一个新的数组。
function map(func, array) { var result = []; forEach(array, function(element) { result.push(func(element)); }); return result;}
第6章 面向对象编程
6.1.1 定义方法
1. 对对象添加方法的一种方式就是简单附加一个函数值,如下面的代码所示。
var rabbit = {};rabbit.speak = function(line) { print("The rabbit says '", line, "'");};rabbit.speak("I'm alive.")
2. 对象可以看成是属性和方法的集合,因此可以用声明集合的方式来声明对象 ~
function speak(line) { alert("The " + this.adjective + " rabbit says '" + line + "'");}var whiteRabbit = {adjective:"white", speak:speak};var fatRabbit = {adjective:"fat", speak:speak};whiteRabbit.speak("Oh my ears and whiskers, how late it's getting!");fatRabbit.speak("I could sure use a carrot right now.");
从.访问speak()来看,这的确是一个对象。但函数与对象的耦合度未免也太低了~
apply()方法和call()方法
1. apply方法的第一个参数用于指定函数所应用的对象(对非方法函数来说,关系并不大,着也是传入null的原因)。也可以通过下面的方式让fatRabbit来调用speak:
speak.apply(fatRabbit, ["Yum."]);
apply(Object, args),第二个参数是speak()的参数数组 (这里speak()函数只接收一个参数) ;
2. call方法可以为函数分别给出相应的参数,而无需将其作为一个数组。
speak.call(fatRabbit, "Yum.");
3. 对于有多个参数的函数,可以按如下方式使用call和apply:
function run(from, to) { alert("The " + this.adjective + " rabbit runs from " + from + " to " + to + " .");}run.apply(whiteRabbit, ["A", "B"]);run.call(fatRabbit, "the cupboard", "the fridge");
6.1.3 从原型中构建
为什么必须使用new关键字呢? 毕竟,我们只需这样编写:
function makeRabbit(adjective) { return { adjective: adjective, speak: function(line) { /*等等*/} };}var blackRabbit = makeRabbit("black");
但两者并不完全相同。new还发挥着一些其他作用。首先,killerRabbit有一个constructor属性,指向创建该属性的Rabbit函数。blackRabbit也有一个这样的属性,但它指向Object函数。
constructor属性从何而来?它是一个rabbit属性的一部分。虽然有点令人迷惑,但是原型是JavaScript对象工作方式中非常重要的一部分。每个对象都基于一个原型,该原型赋予其一系列基本特性。到目前为止所使用的简单对象均基于最基本的原型,这种原型与Object构造函数相关,因此所有对象都共享该原型。(顺便说一句,输入{}相当于输入new Object().)