《JavaScript语言精髓与编程实践》读书拾遗-JavaScript语法

  • JavaScript的6种基本数据类型undefined(未声明的变量,或者声明过但未赋值的变量的值,会是undefined。也可以显式或隐式地给一个变量赋值为undefined),string(不能直接读取或修改字符串中的单一字符),number,boolean,function,object。
  • NaN值,与自身并不等值,也不全等。
  • 在早期Netscape的JavaScript中允许出现非Unicode字符,但现在ECMA标准统一要求JavaScript中的字符串必须是Unicode字符序列。
  • 当一个直接量被识别为十进制整数时,它内部的存放格式可能是浮点数,也可能整型数,这取决于不同引擎的实现,因此不能指望JavaScript中的整型数会有较高的运算性能。
  • 通过rx=/abcd\n\r/gi的直接量方式创建正则表达式对象,其中的转义字符是不能自动转义的,但通过rx=new RegExp(“abcd\n\r”,”gi”)的字符串创建正则表达式对象方式,其中的转义字符则会被自动转义,因此要在字符串中增加转义字符rx=new RegExp(“abcd\\n\\r”,”gi”)。
  • JavaScript中单词形式的运算符:typeof(取变量或值的类型)、void(运算表达式并忽略值,运算返回undefined)、new(创建指定类的对象实例)、in(检查对象属性)、instanceof(检查变量是否指定类的实例)、delete(删除实例属性)。
  • “===”和”!==”比较两个表达式,看是否具有相等的值或相同的数据类型。
  • JavaScript中,赋值是一个运算,而不是一个語句。
  • JavaScript中只有一种方法来完成函数调用,即在函数后紧临函数调用运算符”()”,这个运算符被解释为两个含义:使函数得以执行;从左到右运算并传入”( )”内的参数序列。
  • 当語句位于以下几种情况之一时,可以省略分号:一个文本行或整个文本文件的末尾;在語法分隔符之前(如复合語句的大括号”}”);在复合語句的大括号”}”之后。
  • 語句的返回值由最后的一个子句或表达式的值决定,即使不返回值,也会返回undefined。
  • 没有引用的匿名函数调用方法(1):(function() { /*func body*/}()); 此为用强制运算符使函数调用运算得以执行。
  • 没有引用的匿名函数调用方法(2):(function() { /*func body*/})(); 此为用强制运算符运算“函数直接量声明”这个表达式,并返回一个函数自身的引用,然后通过函数调用运算符”()”来操作这个函数引用。
  • 没有引用的匿名函数调用方法(3):void function() { /*func body*/ }(); 此为调用函数并忽略返回值。
  • JavaScript中的标签就是一个标识符。标签可以与变量重名而互不影响,因为它是另一种独立的語法元素(即不是变量,也不是类型),其作用是指示“标签化語句”。
  • break子句不但可以使用在循环与条件分支内部,也可以使用在标签化語句的内部(break a_label)。
  • continue后面也可以带一个标签,但continue不允许跳转到”当前/外层的单个循环語句的起始”之外的其他任何地方。
  • try{ tryStatements } catch(exception) { catchStatements } finally { finallyStatements };其中,finally{…}語句块的一个重要之处在于它“总是在try/catch块退出之前被执行“,无论在try/catch块中用return/break等退出时,总会执行finally块的代码再退出。
  • 通过”obj = new constructor;”与”obj = new constructor();”创建实例是一致的,实例创建时需要使用一个函数作为“构造器”,但我们不能认为constructor后面的括号就是函数调用的括号。
  • 对象直接量的声明”obj = { propertyName: expression[,...] }比构造函数来得简单方便,这里的propertyName可以用字符串表示,也可以只是一个标识符。因为这是語句語法,所以我们通常都用标识符,只有在特殊的情况下,才使用它的字符串格式,特殊的情况指:使用的标识符不满足JavaScript对标识符的规则;特殊的、强调的属性名。
  • 对象成员可以通过for…in…来列举,需要强调的是可以列举的是“显式的成员名”,其原因在于JavaScript约定了一些隐含的成员名称,例如所有对象都应该具有的”toString”方法。这些名称在for…in…語句中不会被列举出来。对于一些引擎来说,这些隐含的成员名称总是不被列举(例如在JScript引擎中);而对于另一些引擎中,只要覆盖、重写这个名称,它就可以被列举出来了(例如在SpiderMonkey)。因此在跨引擎的设计中,我们并不能依赖于for…in…語句来获取对象成员名称。
  • 可以用delete来删除一个不需要的对象属性,delete obj.property,以使其不能被for…in…語句列举。大多数情况下成员都能被删除,包括对象成员和数组元素,甚至也包括全局对象Global的成员(delete isNaN)。但不能删除的有:用var声明的变量;直接继承自原型的成员。delete不能删除继承自原型的值,但如果修改了这个成员的值,你仍然可以删除它,这将使它恢复到原型的值。关于这一点的真相是:delete运算事实上是删除了实例的成员表中的值。如果真的需要删除该属性,你只能对原型实例进行操作,这样的话会直接影响到这个类构造的所有实例。
  • JavaScript的一些官方文档中提及delete仅在删除一个不能删除的成员时,才会返回false。而其他情况下——例如删除不存在的成员,或者继承自父代类/原型的成员,都应该返回true。这种因“不能删除成员”而返回false的情况不多,大概有Function对象的length、prototype、arguments等极少数的几个——而且这还依赖不同的脚本引擎,例如在Mozilla中arguments就是可以删除的。
  • 按照JavaScript语言的约定,取一个“不存在的属性”的值并不会导致异常,而是返回”undefined”,而”undefined”可以被类型转换为if語句所需的布尔值”false”。
  • instanceof运算符将会检测类的继承关系。因此一个子类的实例,在对祖先类做instanceof运算时,仍会得到true。
  • 对象成员是否能被列举,称为成员的可列举性。当某个对象成员不存在或它不可列举时,则对该成员调用propertyIsEnumerable()方法将返回false(obj.propertyIsEnumerable(‘propertyName’))。比较常见的情况是:JavaScript对象的内置成员不能被列举。这种情况下,可以用”in”运算检测到该成员,但不能用”for…in…”語句来列举它。
  • 原型链/父代类成员也是可以被”for…in…”語句列举的,但它的propertyIsEnumerable()却是false,即propertyIsEnumerable()被实现为“只检测对象的非(自原型链继承而来的)继承属性。
  • 括号”( )”的二义性:
    • typeof作为运算,却可以这样调用typeof(123)。
    • 声明函数时,用作参数表。
    • 在with、for、if、while和do…while等語句,以及catch()等子句中用来作为限定表达式的词法元素,在if、while等語句中括号会有“将表达式結果转换为布尔值”的副作用。
    • 括号”( )”用于强制表达式运算,改变优先级。
    • 作为函数/方法调用运算符。
  • 大括号”{ }”的二义性:
    • 表示“复合語句”。
    • 对象直接量创建。这其中会出现歧义,如eval(‘if (true) { entry : 1 }’)中,’{ entry : 1 }’这部分应该是作为创建的对象还是作为对象返回呢?JavaScript对此作出的解释为“語句优先”,即eval返回的是1,而不是对象。
    • 用于函数直接声明时的語法符号。
    • 大括号也是结构化异常处理的語法符号。之所以是异常处理的語法符号而不是复合語句,是因为如果它是复合語句的語法标识符,那么它必然是可以用单行語句来替代的,但如果在异常处理中用单行語句,则会出现語法错误。
  • 逗号”,”的二义性:
    • 語法分隔符,如数组成员声明,var变量创建。
    • 连续运算符。
  • 方括号”[ ]“的二义性:
    • 数组声明,a = [ [1][1] ] => a = [ undefined ]
    • 下标存取
    • 对象成员存取

This entry was posted in JavaScript. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>