JavaScript 精粹读书笔记(1,2)

第1章 精华
JavaScript的特性中有一部分特性带来的麻烦远远超出它们的价值。其中,一些特性是因为规范很不完善,从而可能导致可移植性的问题;一些特性会导致生成难以理解和修改的代码;一些特性促使我的代码风格过于复杂且易于出错;还有一些特性就是设计错误。有时候语言的设计者也会犯错。
大多数编程语言都有精华部分和鸡肋部分。我发现如果只使用精华部分而避免使用鸡肋的部分,我可以成为一个更好的程序员。毕竟,用糟糕的部件怎么可能构建出好东西呢?
标准委员会想要移除一门语言中的缺陷部分,这几乎是不可能的,因为这样做会损害所有依赖于那些鸡肋部分的糟糕程序。除了在已存在的一大堆缺陷上堆积更多的特性,他们通常无能为力。并且新旧特性并不总是能和谐共处,可能从而产生出更多的鸡肋部分。
但是,你有权力定义你自己的子集。你完全可以基于精华部分去编写更好的程序。JavaScript中鸡肋部分的比重超出了预料。在短到令人吃惊的时间里,它从不存在发展到全球采用。它从来没有在实验室里被试用和打磨。当它还非常粗糙时,它就被直接集成到网景的Navigator 2浏览器中。随着JavaTM的小应用程序(Java applets)的失败,JavaScript变成了默认的“网页语言”。作为一门编程语言,JavaScript的流行几乎完全不受它的质量的影响。
好在JavaScript有一些非常精华的部分。JavaScript最本质的部分被深深地隐藏着,以至于多年来对它的主流观点是:JavaScript就是一个丑陋的、没用的玩具。本书的目的就是要揭示JavaScript中的精华,让大家知道它是一门杰出的动态编程语言。
或许只学习精华部分的最大好处就是你可以不用考虑鸡肋的部分。忘掉不好的模式是非常困难的。这是一个非常痛苦的工作,我们中的大多数人都会很不愿意面对。有时候,制定语言的子集是为了让学生更好的学习。但在这里,我制定的JavaScript子集是为了主专业人员更好的工作。
1.1 为什么要使用JavaScript
JavaScript是一门重要的语言,因为它是web浏览器的语言。它与浏览器的结合使它成为世界上最流行的编程语言之一。同时,它也是世界上最被轻视的编程语言之一。浏览器的API和文档对象模型(DOM)相当糟糕,导致JavaScript遭到不公平的指责。
JavaScript是最被轻视的语言,因为它不是所谓的主流语言。如果你擅长某些主流语言,但却在一个只支持JavaScript的环境中编程,那么被迫使用JavaScript确是相当令人厌烦的。大多数人觉得没必要去先学好JavaScript,但结果他们会惊讶地发现,JavaScript跟他们宁愿使用的主流语言有很大不同,而且这些不同至为关键。
JavaScript令人惊异的事情是,在对这门语言没有太多了解,甚至对编程都没有太多了解的情况下,你也能用它来完成工作。它是一门拥有极强表达能力的语言。当你知道要做什么时,它甚至能表现得更好。编程是很困难的事情。绝不应该在对此一无所知时便开始你的工作。
1.2 分析JavaScript
JavaScript建立在一些非常好的想法和少数非常坏的想法之上。
那些非常好的想法包括函数、弱类型、动态对象和一个富有表现力的字面量表示法。那些坏的想法包括基于全局变量的编程模型。
JavaScript的函数是(主要)基于词法作用域(lexical scoping)的顶级对象。JavaScript是第一个成为主流的lambda语言。实际上,相对Java而言,JavaScript与Lisp和Scheme有更多的共同点。它是披着C外衣的Lisp。这使得JavaScript成为一个非常强大的语言。
现今大部分编程语言中都流行要求强类型。其原理在于强类型允许编译器在编译时检测错误。我们能越早检测和修复错误,付出的代价就越小。JavaScript是一门弱类型的语言,所以JavaScript编译器不能检测出类型错误。另一方面,弱类型其实是自由的。我们无须建立复杂的次,我永远不用做强制类型转换,也不用疲于应付类型系统以得到想要的行为。
JavaScript有非常强大的对象字面量表示法。通过列出对象的组成部分,它们就能简单地被创建出来。这种表示法产生了流行的数据交换格式——JSON。
原型继承是JavaScript中一个有争议的特性。JavaScript有一个无类别(class-free)的对象系统,在这个系统中,对象直接从其他对象继承属性。这真的很强大,但是对那些被训练使用类去创建对象的程序员们来说,原型继承是一个陌生的概念。如果你尝试对JavaScript直接应用基于类的设计模式,你将会遭受挫折。但是,如果你学习使用JavaScript的原型本质,那么你的努力将会有所回报。
JavaScript在关键思想的选择上饱受非议。虽然在大多数情况下,这些选择是合适的。但是有一个选择相当糟糕:JavaScript依赖于全局变量来进行连接。所有编译单元的所有顶级变量被撮合到一个被称为全局对象的公共命名空间中。这是一件糟糕的事情,因为全局变量是魔鬼,并且在JavaScript中它们是基础性的。
在少数情况下,我们不能忽略鸡肋的部分。另外还有一些不可避免的糟粕,当涉及这些部分时,我们会将它们指出来。如果你想学习那些鸡肋的部分及如何拙劣地使用它们,请参阅任何其他的JavaScript书籍。
JavaScript是一门有许多差异的语言。它包含很多错误和尖锐的边角(sharp edges),所以你可能会疑惑:“为什么我要使用JavaScript?”有两个答案。第一个是你没有选择。Web已变成一个重要的应用开发平台,而JavaScript是唯一一门所有浏览器都可以识别的语言。很不幸,Java在浏览器环境中失败了。JavaScript的蓬勃发展,恰恰说明了JavaScript确有其过人之处。
另一个答案是,尽管JavaScript有缺陷,但是它真的很优秀。它既轻量又富有表现力。并且一旦你熟练掌握了它,就会发现函数式编程是一件很有趣的事。
但是为了更好地使用这门语言,你必须知道它的局限。我将会无情地揭示它们。不要因此而气馁。这门语言的精华部分足以弥补它鸡肋的不足。
1.3 一个简单的试验场
如果你有一个Web浏览器和任意一个文本编辑器,那么你就有了运行JavaScript程序所需要的一切。首先,请创建一个HTML文件,可以命名为program.html:


代码如下:

<html>
<body>
<pre>
<script src="program.js"></script>
</pre>
</body>
</html>

接下来,在同一个文件夹内,创建一个脚本文件,可以命名为program.js:
document.writeln('Hello, world!');
下一步,用你的浏览器找开你的HTML文件去查看结果。本书贯彻始终都会用到一个method方法去定义新方法。下面是它的定义:


代码如下:

Function.prototype.method=function(name,func){
this.prototype[name]=func;
return this;
}

我会在第4章解释它。
第2章 语法
本章介绍JavaScript的精华部分的语法,并简要地概述其语言结构。
2.1 空白
空白可能表现为格式化字符或注释的形式。空白通常没有意义,但是偶尔须要用它来分隔字符序列,否则它们就会被合并成一个单一的符号。例如,对如下代码来说:
var that = this;
var和that之间的空格是不能被移除的,但是其他的空格都可以被移除。
JavaScript提供两种注释形式,一种是用/* */包围的块注释,另一种是以//为开头的行注释。注释应该被充分地用来提高程序的可读性。必须注意的是,注释一定要精确地描述代码。没有用的注释比没有注释更糟糕。
用/* */包围的块注释形式来自于一门叫PL/I(默然说话:Programming Language One的简写。当中的“I”其实是罗马数字的“一”,它是一种IBM公司在19世纪50年代发明的第三代高级编程语言)的语言。在JavaScript中,*/可能出现在正则表达式字面上,所以块注释对于被注释的代码块来说是不安全的。例如:
/*
var rm_a = /a*/.match(s);
*/
导致了一个语法错误。所以,我建议避免使用/* */注释,而用//注释代替它。
2.2 标识符
标识符由一个字母开头,其后可选择性地加上一个或多个字母数字或下划线。标识符不能使用下面这些保留字:
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 volatile void
while with
在这个列表中的大部分保留字尚未用在这门语言中。这个列表不包括一些本应该被保留而没有保留的字,诸如undefined、NaN和Infinity。JavaScript不允许使用保留字来命名变量或参数。更糟糕的是,JavaScript不允许在对象字面量中,或者在一个属性存取表达式的点号之后,使用保留字作为对象的属性名。
标识符被用于语句、变量、参数、属性名、运算符和标记。
2.3 数字
JavaScript只有一个单一的数字类型。它在内部被表示为64位的浮点数,和Java的double一样。在JavaScript中,1和1.0是相同的值。
如果一个数字字面量有指数部分,那么这个字面量的值是由e之前的部分乘以10的e之后部分的次方计算出来的。所以100和1e2是相同的数字。
负数可以用前缀运算符-来构成。
值NaN是一个数值,它表示一个不能产生正常结果的运算结果。NaN不等于任何值,包括它自己。你可以用函数isNaN(number)检测NaN。
值Infinity表示所有大于1.79769313486231570e+308的值。
数字拥有方法(参见第8章)。JavaScript有一个对象Math,它包含一套作用于数字的方法。例如,可以用Math.floor(number)方法将一个数字转换成一个整数。
2.4 字符串
字符串字面量可以被包围在单引号或双引号中,它可能包含0个或多个字符。\是转义字符。JavaScript在被创建的时候,Unicode是一个16位的字符集,所以JavaScript中的所有字符都是16位的。
JavaScript没有字符类型。要表示一个字符,只须创建仅包含一个字符的字符串即可。
转义字符允许把那些正常情况下不被允许的字符插入到字符串中,比如反斜线、引号和控制字符。\u约定允许指定用数字表示的字符码位。
“A”===”\u0041”
字符串有一个ength属性。例如,”seven”.length是5。
字符串是不可变的。一旦字符串被创建,就永远无法改变它。但通过+运算符去连接其他的字符串从而得到一个新字符串是很容易的。两个包含着完全相同的字符且字符顺序也相同的字符串被认为是相同的字符串。所以:
‘c'+'a'+'t' === ‘cat'
是true。
字符串有一些方法(参见第8章)。
2.5 语句
一个编译单元包含一组可执行的语句。在web浏览器中,每个<script>标签都提供一个被编译且立即执行的编译单元。因为缺少链接器,JavaScript把它们一起抛入一个公共的全局命名空间中。附录A有更多关于全局变量的内容。
当var语句被用在函数的内部时,它定义了这个函数的私有变量。
switch、while、for和do语句允许有一个可选的前置标签(label),它配合break语句来使用。
语句往往按照从上到下的顺序被执行。JavaScript可以通过条件语句(if和switch)、循环语句(while、for和do)、强制跳转语句(break、return和throw)和函数调用来改变这个执行序列。
代码块是包在一对花括号中的一组语句。不像许多其他的语言,JavaScript中的代码块不会创建一个新的作用域,因此变量应该被定义在函数的顶端,而不是在代码块中。
if语句根据表达式的值改变程序的控制流程。如果表达式的值为真,那么执行then代码块,否则,执行可选的else分支。
下面列出的值被当作假:
fase
null
undefined
数字0
数字NaN
其他所有的值都被当作真,包括true,字符串”false”,以及所有的对象。
switch语句执行一个多路分支。它把其表达式的值和所有指定的case条件进行匹配。其表达式可能产生一个数字或字符串。当找到一个精确的匹配时,执行匹配的case从句中的语句。如果没有找到任何匹配,则执行可选的default语句。
一个case从句包含一个或多个case表达式。case表达式不一定必须是常量。为了防止继续执行下一个case,case语句后应该跟随一上强制跳转语句。你可以用break语句去退出一个switch语句。
while语句执行一个简单的循环。如果表达式值为假,那么循环将终止。而当表达式值为真时,代码块将被执行。
for语句是一个结构更复杂的循环语句。它有两种形式。
常见的形式由三个可选从句控制:初始化从句(initialization)、条件从句(condition)和增量从句(increment)。首先,;初始化从句被执行,它的作用通常是初始化循环变量。接着计算条件从句的值。典型的情况是它根据一个完成条件检测循环变量。如果条件从句被省略掉,则假定返回的条件是真。如果条件从句的值为假,那么循环将终止。否则,执行代码块,然后执行增量从句,接着循环会重复执行条件从句。
另一种形式(被称为for in语句)会枚举一个对象的所有属性名(或键名)。在每次循环中,对象的另一个属性名字符串被赋值给for和in之间的变量。
通常你须通过检测object.hasOwnProperty(variable)来确定这个属性名就是该对象的成员,还是从其原型链里找到的。


代码如下:

for(myvar in obj){
if(obj.hasOwnProperty(myvar)){

}
}

do语句就像while语句,唯一的区别是它在代码块执行之后而不是之前检测表达式的值。这就意味着代码块将总是要执行至少一次。
try语句执行一个代码块,并捕获该代码块抛出的任何异常。catch从句定义了一个新的变量,它将接收该异常对象。
throw语句抛出一个异常。如果throw语句在一个try代码块中,那么控制权会跳到catch从句中。如果throw语句在函数中,则该函数调用被放弃,且控制权会跳到调用该函数的try语句的catch从句中。
throw语句中的表达式通常是一个对象字面量,它包含一个name属性和一个message属性。异常捕获器可以使用这些信息去决定该做什么。
return语句会使一人函数提前返回。它也可以指定要被返回的值。如果没有指定返回表达式,那么其返回值是undefined。
JavaScript不允许在return关键字和表达式之间换行。
break语句会使程序退出一个循环语句或switch语句。它可以指定一个可选的标签,那将会使程序退出带该标签的语句。
JavaScript不允许在break关键字和标签之间换行。
一个expression语句可以给一个或多个变量或成员赋值,或者调用一个方法,或者从对象中删除一个属性。运算符=被用于赋值。不要把它和恒等运算符===混淆。运算符+=可以用于加法运算或连接字符串。
2.6 表达式
三元运算符?有三个运算数。如果第一个运算数值为真,它产生第二个运算数的值。但是,如果第一个运算数为假,它会产生第三个运算数的值。
表2-1:运算符优先级





























.[]()

属性存取及函数调用

delete new typeof +-!

一元运算符

*/%

乘法、除法、取模

+-

加法/连接、减法

>= <= > <

不等式运算符

=== !==

等式运算符

&&

逻辑与

||

逻辑或

?:

三元

typeo运算符产生的值有'number'、'string'、'boolean'、'undefined'、'function'、'object'。如果运算数是一个数组或null,那么结果是'object',这是不对的。第6章和附录A将会有更多关于typeof的内容。
/运算符可能会产生一个非整数结果,即使两个运算数都是整数。
函数调用引发函数的执行。函数调用运算符是跟随在函数名后面的一对圆括号。圆括号中可能包含将会传递给这个函数的参数。第4章将会有更多关于函数的内容。
一个属性存取表达式用于指定一个对象或数组的属性或元素。下一章我将详细描述它。
2.7 字面量
对象字面量是一种方便指定新对象的表示法。属性名可以是标识符或字符串。这些名字被当作字面量名而不是变量名来对待,所以对象的属性名在编译时才能知道。属性的值就是表达式。下一章将会有更多关于对象字面量的信息。
数组字面量是一个方便指定新数组的表示法。第6章将会有更多关于数组字面量的内容。
第7章将会有更多关于正则表达式的内容。
函数字面量定义了函数值。它可以有一个可选的名字,用于递归地调用自己。它可以指定一个参数列表,这些参数将作为变量由调用时传递的实际参数(arguments)初始化。函数的主体包括变量定义和语句。第4章将会有更多关于函数的内容。

(0)

相关推荐

  • javascript 面向对象的经典实例代码

    [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] JavaScript面向对象编程http://www.jb51.net/article/13661.htm

  • JavaScript 经典实例日常收集整理(常用经典)

    本文是小编日常收集整理些js经典实例,特此分享到我们平台供大家参考! 跨浏览器添加事件 //跨浏览器添加事件 function addEvent(obj,type,fn){ if(obj.addEventListener){ obj.addEventListener(type,fn,false); }else if(obj.attachEvent){//IE obj.attchEvent('on'+type,fn); } } 跨浏览器移除事件 //跨浏览器移除事件 function remove

  • JavaScript语言精粹经典实例(整理篇)

    数据类型 JavaScript 是 弱类型 语言,但并不是没有类型,JavaScript可以识别下面 7 种不同类型的值: 基本数据类型 1.Boolean 2.Number 3.String 4.null 5.undefined 6.Symbol Object 1.Array 2.RegExp 3.Date 4.Math 5.... 可以使用 typeof 判断数据类型,操作符返回一个字符串,但并非返回的所有结果都符合预期 typeof false // "boolean" type

  • javascript 精粹笔记

    //为构造函数原型添加方法 Function.method=function(name,func){ this.prototype.name=func; } Number.method("integer",function(){ return Math[this < 0 ? 'ceil':'floor'](this); }); (-10/3).integer();//-3 String.method("trim",function(){ return this

  • JavaScript 语言精粹学习笔记第1/2页

    非常好的想法包括函数,弱类型,动态对象和一个富有表现力的对象字面量的表示法, 坏的想法包括基于全局变量的编程模型. JavaScript的函数是基于词法作用域的顶级对象.Javascript是第一个成为主流的Lambda语言.相对于Java而言,JavaScript于Lisp和Scheme有更多的共同点.它是披着C外衣的Lisp.这使得JavaScript成为一个非常强大的语言. 现在大部分变成语言都流行要求强类型.其原理在于强类型允许编译器在编译时检查错误.我们越早检查和修复错误,付出的代价越

  • js正则表达式基本语法(精粹)

    1.正则表达式基本语法 两个特殊的符号'^'和'$'.他们的作用是分别指出一个字符串的开始和结束. 例子如下: "^The":表示所有以"The"开始的字符串("There","The cat"等): "of despair$":表示所以以"of despair"结尾的字符串: "^abc$":表示开始和结尾都是"abc"的字符串--呵呵,只有&q

  • JavaScript 精粹读书笔记(1,2)

    第1章 精华 JavaScript的特性中有一部分特性带来的麻烦远远超出它们的价值.其中,一些特性是因为规范很不完善,从而可能导致可移植性的问题:一些特性会导致生成难以理解和修改的代码:一些特性促使我的代码风格过于复杂且易于出错:还有一些特性就是设计错误.有时候语言的设计者也会犯错. 大多数编程语言都有精华部分和鸡肋部分.我发现如果只使用精华部分而避免使用鸡肋的部分,我可以成为一个更好的程序员.毕竟,用糟糕的部件怎么可能构建出好东西呢? 标准委员会想要移除一门语言中的缺陷部分,这几乎是不可能的,

  • javascript框架设计读书笔记之种子模块

    1.命名空间: js里面的命名空间就是使用对象的属性来扩展的.比如,用户定义一个A对象,A对象下面有B属性和C属性,同时B属性和C属性又是对象.因此A={B:{},C:{}},这时用户就可以在B对象和C对象中定义一样的方法,属性了.因此B和C就属于不同的命名空间.我们调用B,C对象里面的方法,就可以通过A.B.like(),A.C.like()调用了.当然A属于window对象中的属性. 但是有一种情况,比如:boke.jsp页面引入了jquery.js以及prototype.js(他们都会在w

  • JavaScript高级程序设计 读书笔记之八 Function类及闭包

    Function类 定义 Function类可以表示开发者定义的任何函数,用Function类直接创建函数的语法如下: var function_name=new Function(agrument1,agrument2,...,argumentN,function_body); 每个argument都是一个参数,最后一个参数是函数主体(要执行的代码). 示例: 复制代码 代码如下: function sayHi(sName,sMessage){ alert("Hello "+sNam

  • InnoDb 体系架构和特性详解 (Innodb存储引擎读书笔记总结)

    后台线程 •Master Thread 核心后台线程,主要负责将缓冲池的数据异步刷新到磁盘.例如脏页的刷新,插入缓冲的合并,undo 页的回收等. 每秒一次的操作: 1.日志缓冲刷新到磁盘,即使该事务还没有提交.该操作总是会发生,这个就是为了再大的事务,提交时间都很短. 2.当IO压力很小时(1s内发生的IO次数小于5% innodb_io_capacity)合并5% innodb_io_capacity 的插入缓冲. 3.当脏页比例大于 innodb_max_dirty_pages_cnt,

  • MYSQL必知必会读书笔记第十和十一章之使用函数处理数据

     mysql简介 MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言--结构化查询语言(SQL)进行数据库管理. 拼接字段 存储在数据库表中的数据一般不是应用程序所需要的格式.我们需要直接从数据库中检索出转换.计算或格式化过的数据:而不是检索出数据,然后再在客户机应用程序或报告程序中重新格式化. 计算字段(字段 = 列,不过数据库列一般称为列,而字段通常用于计算字段中)并不实际存在于数据库表中,计算字段是运行时在select语句内创建的

  • JavaScript继承学习笔记【新手必看】

    JavaScript作为一个面向对象语言(JS是基于对象的),可以实现继承是必不可少的,但是由于本身并没有类的概念,所以不会像真正的面向对象编程语言通过类实现继承,但可以通过其他方法实现继承.实现继承的方法很多,下面就只是其中的几种. 一. 原型链继承 function Person() { //被继承的函数叫做超类型(父类,基类) this.name='mumu'; this.age='18'; } Person.prototype.name='susu';//当属性名相同时需就近原则,先在实

  • Javascript基础学习笔记(菜鸟必看篇)

    什么是变量? 变量是用于存储信息的容器 变量的声明 语法: var 变量名 变量名 = 值; 变量要先声明再赋值 变量可以重复赋值 变量的命名规则 变量必须以字母开头: 变量也能以$和_符号开头(不过我们不推荐这么做): 变量名称对大小写敏感(a和A是不同的变量). 语句 语句以一个分号结尾:如果省略分号,则由解析器确定语句的结尾. 有个好的编码习惯,都要以 ; 结尾 数据类型 在JavaScript中,一段信息就是一个值(value).值有不同的类型,大家最熟悉的类型是数字.字符串(strin

  • PHP读书笔记_运算符详解

    什么是运算符 什么是运算符?运算符是告诉PHP做相关运算的标识符号.例如,你需要计算123乘以456等于多少,这时候就需要一个符号,告诉服务器,你需要做乘法运算. PHP中的运算符有哪些?PHP运算符一般分为算术运算符.赋值运算符.比较运算符.三元运算符.逻辑运算符.字符串连接运算符.错误控制运算符. PHP中的算术运算符 算术运算符主要是用于进行算术运算的,例如:加法运算.减法运算.乘法运算.除法运算.在PHP中的常用的算术运算符对应下表: PHP中的赋值运算符 PHP的赋值运算符有两种,分别

  • PHP读书笔记整理_结构语句详解

    PHP结构语句顺序结构 顺序结构就像一条直线,按着顺序一直往下执行.我们编写的代码默认都是按照顺序结构执行的. 条件结构之if-else- 条件结构就像一个岔路口,可以向左走,也可以向右走.比如上洗手间,我们知道我们的性 别,这时候我们需要根据洗手间提供的条件,左边男洗手间,右边女洗手间,或者正好相反,其中性别就是这个条件结构的条件.再比如,现在的分数都流行使用 A.B.C来分级,假设考试成绩是93分,可以将其设置为等级A,考试成绩是87,可以将其设置为等级B,这里分数区间即为条件结构中的条件.

  • MYSQL必知必会读书笔记第六章之过滤数据

    mysql简介 MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言--结构化查询语言(SQL)进行数据库管理. where子句的位置,在同时使用ORDER BY 和WHERE子句时应该让ORDER BY 位于where之后,否则会产生错误. 1.不匹配检查 复制代码 代码如下: SELECT vend_id FROM products where vend_id <>1003 等同于 复制代码 代码如下: SELECT vend_id

随机推荐