javaScript之词法结构、类型、值与变量

词法结构

字符集

JavaScript是区分大小写的语言。但是HTML并不区分大小写(XHTML区分大小写)

严格上讲XHTML是区分大小写的,但是由于浏览器的纠错,实际上基本不区分/

JavaScript会忽律程序中标识之间的空格。


Unicode标准为所有字符定义了一个首选的编码格式,并给出了一个标准化对处理方式讲文本转换为一种适合比较对标准格式,JavaScript会认为它正在解析对程序代码已经是这种标准格式,不会再对起标识符、字符串或正则表达式做标准化处理。


直接量、标识符和保留字

所谓直接量,就是程序中直接使用对数据值。

标识符就是一个名字,在JavaScript中,标识符必须以字母、下划线和美元符开始。

出于可移植性和易于书写对考虑,通常我们只使用ASCII字母和数字来书写标识符。然而需要注意的是,JavaScript允许标识符中出现Unicode字符全集中的字母和数字。

JavaScript的具体实现可能定义独有的全部变量和函数,每一种特定的JavaScript运行环境(客户端、服务器端)都有自己的一个全局属性列表。


可选的分号

var y = x+f
(a+b).toString()
但第二行但愿活好却和第一行但f组成了一个函数调用,实际上会被看为
var y = x+ f(a+b).toString()

通常来讲,如果一条语句以(、[、/、+、-开始,则非常可能与前一条语句一起解析

如果当前语句和下一行语句无法合并执行,JavaScript则在第一行后填补分号,这是通用规则。但有两个例外。第一个例外是涉及return、break和continue语句的场景。在rerurn、break、continue和随后的表达式之间不能有换行。第二个例外是涉及++和--运算符的适合。例如:
x
++
y
这段代码将被解析为"x;++y"而不是"x++,y"

类型、值与变量

概述

JavaScript的数据类型分为两类:原始类型和对象类型。

除数字、字符串、布尔值、null、undefined之外都是对象。

除数组类和函数类之外。JavaScript语言核心定义了其它三种有用的类——日期(Date)类定义了日期对象。正则(RegExp)类定义类表示正则表达式的对象。错误(Error)类定义类那些表示JavaScript程序中运行时错误和语法错误的对象。

从技术上,只有对象才能拥有方法,然而,数字、字符串和布尔值也可以拥有自己的方法。只有undefined和null是无法拥有方法的值。

JavaScript的类型可以分为原始类型和对象类型,也可分为可以拥有方法的类型和不能拥有方法的类型,同样可分为可以变(mutable)类型和不可变(immutable)类型。对象和数组属于可变类型:JavaScript成语可以更改对象属性值和数组元素的值。数字、布尔值、null和undefined属于不可不类型。字符串类似于数组,然而字符串是不可变的。

JavaScript采用词法作用域。不在任何函数内声明的变量叫做全局变量。在函数内声明的变量具有函数作用域,并且只在函数内可见。

数字

JavaScript不区分浮点数和整数。
整数范围为-2^53~2^53
JavaScript中的实际曹走是基于32位整数。
当一个数字直接出现在JavaScript中时,我们称其为数字直接量。
某些JavaScript不支持8进制,因此最好不要写0开头的数字。

JavaScript的算数运算在溢出,下溢霍被零整出时不会报错。当数字运算结果超过了JavaScript的数字上限,结果为一个特殊的无穷大值,为Infinity。
下溢是当运算结果无限接近于0并比JavaScript能表示的最小值还小的时候所发生的情况,该情况下程序会返回0.当负数下溢时会返回一个负0.

JavaScript预定义了全局变量Infinity和NaN,用来表示正无穷大和非数字值。
负0值有些特殊,是和正0值相等。这两个值几乎一模一样,除了作为被除数。

JavaScript采用了IEEE-754浮点表示法。
0.3-0.2==0.2-0.1
//false
由于摄入误差,导致上述结果。这种计算结果可以胜任大多数的巨酸任务;这个问题也只有在比较两个数是否相等时候才出现。

文本

JavaScript采用UTF-16编码的Unicode字符集,有时候出现两个长度的字符串来表示一个Unicode。

在ES5中,字符串可以拆分为数行,美航必须以反斜线(\)结束

"adsf\
asdg\
hello world"
//"adsfasdghello world"

一般在javaScript表达式中使用单引号表示字符串,HTML中使用双引号。

在JavaScirpt中字符串是固定不变的,各种方法都是返回新字符串,字符串本身未改变。

字符串可以当成只读数组。

布尔值

在判断语句中,undefined、null、0、-0、NaN、“”(空字符串)会被转化为false,其它都为true

布尔值包含toString()方法,因此可以使用这个方法将布尔值转化为字符串“true”和“false”(本处犀牛书有误)
true.toString()   //"true"
true.toString()==true   //false

null和undefined

null是JavaScript语言的关键字,表示空值。
typeof null的结果是object。
typeof undefined 的结果是 “undefined”
typeof null   //"object"
typeof undefined   //"undefined"

null和undefined都不包含任何属性方法,任何读取这两个值的成员变量或方法都会报错
null.a

//VM1878:1 Uncaught TypeError: Cannot read property 'a' of null
//    at <anonymous>:1:5


全局对象

全局对象的属性是全局定义和符号,JavaScript程序可以直接使用。当JavaScript解释器启动时(或任何web浏览器加载刷新页面时),它将创建一个新的全局变量,并给它一组定义的初始属性:
全局属性(如undefined,NaN)、全局函数(如isNaN(),eval()),构造函数(Date())、全局对象(如Math)

全剧对象的初始属性不是保留字,但应该被当作保留字来对待。

Windows对象定义来核心全局属性,但它也针对Web浏览器和客户端JavaScript定义来一少部分其它全局属性

当初次创建的时候,全剧对象定义了JavaScript中所有的预定义全局值。这个特殊对象同样包括了为程序定义的全局值。如果代码声明了一个全局变量,这个全局变量就是全局对象的一个属性。


包装对象

只要引用了字符串s的属性,JavaScript就会将字符串值通过调用new String(s)的方式转换成对象,这个对象继承了字符串的方法,并被用来处理属性的引用。一旦属性引用结束,这个新创建的对象就会销毁(其实在实现上并不一定创建或销毁这个临时对象,然而整个过程看起来如此)

也就是说,无法在字符串上定义属性或方法。

null和undefinded没有包装对象,访问其属性会造成类型错误。

由于字符串、数字和布尔值的属性都是只读的,并且不能给它们定义新的属性,因此它们是有别于对象的

a=true
a1=Boolean(a)
a===a1
//true

a=true
a1=new Boolean(a)
a===a1   //false

a=true
a1=new Boolean(a)
console.log(typeof a)
console.log(typeof a1) 

//VM4002:3 boolean
//VM4002:4 object

"=="将原始值和其包装对象视为相等,但“===”视为不等。通过typeof可以看到原始值和其包装对象的不同

不可变的原始值和可变的对象引用

JavaScript中的原始值(undefined、null、布尔值、数字和字符串)与对象(包括数组和函数)有着本质区别——原始值不可更改,任何方法都无法改变一个原始值。
字符串的方法看似可以返回一个修改后的字符串,实际上是返回一个新的字符串

如果是单独的两个字符串,当且仅当它们长度相等和美国索引的字符都相等时,JavaScript才认为它们相等。

"adfsga"=="adfsga"  //true
"adfsga"==="adfsga"  //true

对象的比较并非值的比较,而是比较引用是否指向同一个对象。


类型转换

P49

一个值转化为另一个值并不意味着两者相等(null可以转化为0但是null!==0)

当不通过new运算符调用这些函数时,它们会作为类型转换函数进行转换。

如果试图把null或undefined转换为对象,则会抛出一个类型错误(TypeError)。Object()在这种条件下不会抛出异常:它仅简单地返回一个新创建的空对象。

new Object(undefined)   //Object {}
Object(undefined)    //Object {}
Number的toString()方法可以接受转化参数,若不指定,转化规则基于十进制。
var a=17;
console.log(a.toString(2))  //10001
console.log(a.toString(8))   //21
console.log(a.toString(16))  //11

toFixed()根据小数点后指定位数的字符串,不使用指数计数法。
toExponential()使用指数计数法将数字转换为指数形式的字符串,其中小数点只有意味。
toPrecision()根据指定的有效数字位数将转化为字符串。
Number()不能有非法尾随字符。

valueOf():如果存在仁义原始值,他就默认将对象转换为表示它的原始值。

JavaScript对象转化为字符串经历如下步骤:
  1. 若存在toString()方法,则调用,若返回一个原始值,则返回一个相应的字符串
  2. 若没有toString,或没有返回一个原始值,则调用valueOf()方法。若返回原始值,则返回相应字符串
  3. 无法获得一个原始值,则抛出一个类型异常错误

对象转化为数字经历如下步骤:

  1. 如果具有valueOf(),返回一个原始值,则转化为数字并返回
  2. 否则,若具有toString()方法,返回一个原始值,转化为数字并返回
  3. 报错

对象转数字的细节解释了为什么空数组会被转化为数字0以及为什么只有一个数字元素的数组会被转化为相应数字

日期类书JavaScript语言核心中唯一的预先定义类型,它定义了有意义的向字符串和数字类型的转换,对于所有非日期对象来说,对象到原始值的转换基本都是对象到数字的转换。

和“==”以及">"一样,除日期外所有对象都会先调用valueOf()方法再调用toString()。不管得到的原始值都是否直接使用,都不会进一步转化为字符串货数字??????


变量声明

使用var语句重复声明变量是合法且无害的。如果重复声明带有初始化器,那么这就和一条简单的语句没有区别。
应该始终使用var声明变量


变量作用域

尽管在全局作用域编写代码是可以不屑var,但声明局部变量时必须使用var语句。
js存在变量声明提前。
scope="global"
function checkscope(){
    scope="local";
    myscope="local";
    return [scope,myscope];
}
checkscope()
console.log(scope)   //local
console.log(myscope)  //local

scope="global"
function checkscope(){
    var scope="local";
    var myscope="local";
    return [scope,myscope];
}
checkscope()
console.log(scope)  //global
console.log(myscope)  //报错

当使用var声明一个变量时,创建的这个属性时不可配置的,也就是说不能通过delete删除,如果在非严格模式下不用var,则可以

对于嵌套函数,每次调用外部函数时,内部函数又会重新定义一遍。因为没吃调用外部函数的时候,作用域链都是不同。内部函数都会在每次定义的时候都有区别——在每次调用外部函数时,内部函数代码都是相同的,而且关联这段代码的作用域链也不相同。



本座回来了,接下来会写整本犀牛书的博客


版权声明:本文为diaotai原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。