系统学习JS,
从《JavaScript高级程序设计》入门,通过学习jQuery或者angularJS源码来进阶。
第1章 JavaScript简介
1.JS问世的目的是处理以前由服务器端语言(如Perl)负责的一些输入验证操作,
由Netscape主导开发,那时候微软的IE还不能独领风骚。最初叫做LiveScript,当时媒体热炒Java,于是改名为JavaScript。
JavaScript和ECMAScript通常指同一门语言,但是,JavaScript是ECMA-262标准的实现和扩展。ECMAScript应该被称作JavaScript的子集。
2.一个完整的JavaScript实现应该由下列三个不同的部分组成:
核心(ECMAScript)
ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会)通过ECMA-262标准化的脚本程序设计语言。
文档对象模型(DOM)
是针对XML但经过扩展用于HTML的应用程序编程接口,即API。DOM把整个页面映射为一个多层节点结构。
HTML或XML页面中的每个组成部分都是某种类型的节点,这些节点又包含着不同类型的数据。
浏览器对象模型(BOM)。
开发人员使用BOM可以控制浏览器显示的页面以外的部分。但是BOM并没有相关的标准,直到HTML5的出现。HTML5把很多的BOM功能写入正式规范。
第2章 在HTML中使用JavaScript
1.只要你在大学课堂上了解过HTML页面,就不会对这个陌生。
向HTML页面中插入JavaScript的主要方法,就是使用<Script>元素。使用这个元素可以让脚本与标记混合在一起,也可以包含外部的JavaScript文件。随便打开一个网页,查看源代码或者是F12,就会了解到如何在页面中嵌入JS脚本。
需要注意的是,<Script>元素会按照它们在页面中出现的先后顺序被解析。使用defer和async属性可以控制解析的顺序。defer 属性可以让脚本在文档完全呈现之后再执行。async属性表示当前脚本可以异步执行,不必等待其他脚本,也不必阻塞文档呈现。
不过,async 属性仅适用于外部脚本(只有在使用 src 属性时),这也是HTML5的新属性。
2.<noscript>元素可以指定在不支持脚本的浏览器中显示的替代内容。但是如果页面启用了脚本。
<noscript>标签中的元素就会如同被注释掉一样不会显示。
不过现在不支持脚本语言的浏览器应该找不到了吧?
下面是W3C的一段页面代码,简洁明了:
<body> ... ... <script type="text/javascript"> <!-- document.write("Hello World!") //--> </script> <noscript>Your browser does not support JavaScript!</noscript> </body>
第3章 基本概念
这一章介绍了JS基本的语法。JS的语法和C语言或者其他编程语言类似,简单整理,重点学习JavaScript的特性。
1.ECMAScript 5 引入了严格模式(strict mode)的概念。严格模式为JS定义了一种不同的解析与执行模型。
在顶部添加代码:"use strict"即可。
2.关于ECMAScript的关键字,下面说明相关的用途。
break
do
instanceof typeof 和 instanceof 常用来判断一个变量是否为空,或者是什么类型的,
typeof 对一个值使用typeof操作符,可能返回下列某个字符串:
undifined boolean string number object
function ——如果这个值是函数。
debugger
default
delete 可以删除对象的某个属性
注意,以下的列表词组也许在其他的语言,比如C、Java等都是关键字,但是在JS中并没有实质的意义,
被称作保留字,同样不能用作标识符。保留字可以方便JS以后的扩展,也可以防止程序被误读。
当然,不同的ECMAScript版本对保留字的限制有区别。
abstract
boolean break byte
case catch char class const continue
debugger default delete do double
else enum export extends
false final finally float for function goto
if implements import in instanceof int interface
long native new null
package private protected public
return
short static super switch synchronized
this throw throws transient true try typeof
var void volatile
while with
3.定义变量时使用var操作符,如:var message;
这行代码定义了一个名为message的变量,该变量可以用来保存任何值,初始化以前,会保存一个特殊的值——undefined,
当然也可以直接初始化:var message = "hi";
和Java等语言一眼,JS的变量也有作用域,所有使用var定义的变量将成为定义该变量的作用域中的局部变量,如果省略var,
就可以创建一个全局变量。不过并不推荐这样做。比如:
function test(){ var message = "hi";//局部变量 } test(); alert(message);//错误,去掉var则正确、
4.ECMAScript有5种简单数据类型:Undefined/Null/Boolean/Number和String,另外一种复杂数据类型,Object,
Object本质上是由一组无序的名值对组成的。
特别的,要理解Undefined类型的意义,作用在于正式区分对象指针与未经初始化的变量。
和Undefined类似,Null类型也是只有一个值的数据类型,null值表示一个空对象指针,所以使用typeof检测null值时会返回"object"。
var car = null; alert(typeof car); //"object"
如果定义的变量准备用于保存对象,那么最好将该变量初始化为null,这样检查null值就可以知道是否已经保存一个对象的引用。
if( car = null ){ //执行操作 } 另外,undefined的值派生自null值,所以: alert(null == undefined); //true
5.Boolean 类型有个函数特别好玩,
var msg = "hello world!"; var msgAsBoolean= Boolean(msg); 在其他的编程语言中,肯定想不到还有这样的用法。 Boolean true false String 任何非空字符串 "" 空字符串 Number 任何非零数值 0和NaN Object 任何对象 null Undefined n/a undifined
这些转换规则应用在流控制语句,如if语句中。
var msg= "hello world!"; if(msg){ alert("value is true!"); }
如果不了解上面的规则,肯定很难理解这段代码。
6.与其他语言不同,ECMAScript 没有为整数和浮点数值分别定义不同的数据类型,Number类型可用于表示所有数值。
Number类型对不同进制数据的处理,
var num1=070; //八进制的56
var num2=079; //无效的八进制——79
var num3=08; //无效的八进制——8
String 类型,双引号或者单引号都可以表示,
Object类型是ECMAScript中所有对象的基础类型。
7.JS的语句与其他编程语言类似,比如
for-in语句用来迭代,for(property in expression) statement,如
for(var proName in window){ document.write(proName); }
使用Label语句可以在代码中添加标签,以便将来使用:
label: statement,如
start:for(var i=0;i<count;i++){ alert(i); }
with语句的作用是将代码的作用域设置到一个特定的对象中。
with (expression)statement
8.ECMAScript 函数不存在函数签名的特性。没有重载,相同的语法出现在在JS中,只有后定义的函数有效。
9.
《JavaScript语言精粹》一书中列出了一些不建议的JS语法,我们来看一下。
1. == Javascript有两组相等运算符,一组是==和!=,另一组是===和!==。前者只比较值的相等,后者除了值以外,还比较类型是否相同。 请尽量不要使用前一组,永远只使用===和!==。因为==默认会进行类型转换,规则十分难记。如果你不相信的话,请回答下面五个判断式的值是true还是false: false == ‘false‘ false == undefined false == null null == undefined 0 == ‘‘ 前三个是false,后两个是true。 2. with with的本意是减少键盘输入。比如 obj.a = obj.b; obj.c = obj.d; 可以简写成 with(obj) { a = b; c = d; } 但是,在实际运行时,解释器会首先判断obj.b和obj.d是否存在,如果不存在的话,再判断全局变量b和d是否存在。这样就导致了低效率,而且可能会导致意外,因此最好不要使用with语句。 3. eval eval用来直接执行一个字符串。这条语句也是不应该使用的,因为它有性能和安全性的问题,并且使得代码更难阅读。 eval能够做到的事情,不用它也能做到。比如 eval("myValue = myObject." + myKey + ";"); 可以直接写成 myValue = myObject[myKey]; 至于ajax操作返回的json字符串,可以使用官方网站提供的解析器json_parse.js运行。 4. continue 这条命令的作用是返回到循环的头部,但是循环本来就会返回到头部。所以通过适当的构造,完全可以避免使用这条命令,使得效率得到改善。 5. switch 贯穿 switch结构中的case语句,默认是顺序执行,除非遇到break,return和throw。有的程序员喜欢利用这个特点,比如 switch(n) { case 1: case 2: break; } 这样写容易出错,而且难以发现。因此建议避免switch贯穿,凡是有case的地方,一律加上break。 switch(n) { case 1: break; case 2: break; } 6. 单行的块结构 if、while、do和for,都是块结构语句,但是也可以接受单行命令。比如 if (ok) t = true; 甚至写成 if (ok) t = true; 这样不利于阅读代码,而且将来添加语句时非常容易出错。建议不管是否只有一行命令,都一律加上大括号。 if (ok){ t = true; } 7. ++和-- 递增运算符++和递减运算符--,直接来自C语言,表面上可以让代码变得很紧凑,但是实际上会让代码看上去更复杂和更晦涩。因此为了代码的整洁性和易读性,不用为好。 8. 位运算符 Javascript完全套用了Java的位运算符,包括按位与&、按位或|、按位异或^、按位非~、左移<<、带符号的右移>>和用0补足的右移>>>。 这套运算符针对的是整数,所以对Javascript完全无用,因为Javascript内部,所有数字都保存为双精度浮点数。如果使用它们的话,Javascript不得不将运算数先转为整数,然后再进行运算,这样就降低了速度。而且"按位与运算符"&同"逻辑与运算符"&&,很容易混淆。 9. function语句 在Javascript中定义一个函数,有两种写法: function foo() { } 和 var foo = function () { } 两种写法完全等价。但是在解析的时候,前一种写法会被解析器自动提升到代码的头部,因此违背了函数应该先定义后使用的要求,所以建议定义函数时,全部采用后一种写法。 10. 基本数据类型的包装对象 Javascript的基本数据类型包括字符串、数字、布尔值,它们都有对应的包装对象String、Number和Boolean。所以,有人会这样定义相关值: new String("Hello World"); new Number(2000); new Boolean(false); 这样写完全没有必要,而且非常费解,因此建议不要使用。 另外,new Object和new Array也不建议使用,可以用{}和[]代替。 11. new语句 Javascript是世界上第一个被大量使用的支持Lambda函数的语言,本质上属于与Lisp同类的函数式编程语言。但是当前世界,90%以上的程序员都是使用面向对象编程。为了靠近主流,Javascript做出了妥协,采纳了类的概念,允许根据类生成对象。 类是这样定义的: var Cat = function (name) { this.name = name; this.saying = ‘meow‘ ; } 然后,再生成一个对象 var myCat = new Cat(‘mimi‘); 这种利用函数生成类、利用new生成对象的语法,其实非常奇怪,一点都不符合直觉。而且,使用的时候,很容易忘记加上new,就会变成执行函数,然后莫名其妙多出几个全局变量。所以,建议不要这样创建对象,而采用一种变通方法。 Douglas Crockford给出了一个函数: Object.beget = function (o) { var F = function (o) {}; F.prototype = o ; return new F; }; 创建对象时就利用这个函数,对原型对象进行操作: var Cat = { name:‘‘, saying:‘meow‘ }; var myCat = Object.beget(Cat); 对象生成后,可以自行对相关属性进行赋值: myCat.name = ‘mimi‘; 12. void 在大多数语言中,void都是一种类型,表示没有值。但是在Javascript中,void是一个运算符,接受一个运算数,并返回undefined。 void 0; // undefined 这个命令没什么用,而且很令人困惑,建议避免使用。