接触javascript也有很长一段时间了,但是一直以来对其中的一些东西都感觉比较模糊,疑惑也越积越多。最近才终于在多看买到电子书,下定决心把《javascript权威指南》这本书好好啃一遍。今天看了前两章关于词法结构和类、变量、对象的基础知识,了解了javascript这种动态语言在结构上和C、java这种强类型语言的一些差别之后,才发现自己以前的了解是多么浅薄,而看似相同的语言内在上几乎有着本质的区别。一本好书总能在某种方面更新你的观念,这就是这种经典的魅力所在吧!
词法结构
字符集
unicode,支持地球上几乎所有在用的语言
区分大小写
空格、换行符
unicode转义序列
老旧电脑用六个ascii码代表16位unicode内码如\u00e9
标准化
注释
//或/* */
直接量
数字、小数、字符串、boolean、null、正则表达式直接量 {x:1,y:2}
标识符和保留字
字母、_或$开始
可选的分号
return、break、continue和随后的表达式之间不能有换行 ++和--会和后一行合并
类型、值和变量
数据类型
原始类型
包括 undefined\null\布尔值\数字\字符串
特殊的原始值
null\undefined:无法拥有方法
对象类型
对象是属性的集合,每个属性由名值对构成
特殊的对象——函数
构造函数
使用new,初始化一个对象
子类型——类
日期
正则
错误
数字
不区分整数和浮点数,64位浮点格式表示数字 负号是一元求反运算
整型直接量
十六进制 0xff 八进制直接量以0开始
浮点直接量
- 3.14
- .333 * 6.02e23
- 1.23e-4
算术运算
Math.pow()
Math.round()
Math.ceil() //向上取整
Math.floor() //向下取整
Math.abs() //求绝对值
Math.max(x,y,x) //求最大是
Math.min(x,y,x)
Math.random()
Math.PI
Math.E
Math.sqrt()
Math.sin
Math.cos
Math.log
Math.exp
无穷大 infinity 0除以0 NaN NaN和任何值都不相等,包括自身,应使用x!=x判断或者isNaN()
日期和时间
Date()构造函数
new Date(2011,0,1)
new Date(2011,0,1,17,10,20)
new Date()
now-then //计算间隔毫秒数
now.getFullYear() //2013
now.getMonth() ///0
now.getDate() //从1开始的天数
now.getHours() //17:5pm
now.getDay() //星期几 0星期日
getUTCHours() //使用UTC表示小时的时间,基于时区
文本
字符串是由一组由16位值组成的不可变的有序序列采用UTF-16编码的unicode集
字符串直接量
"helloWord"
转义字符
一般的转义和unicode转义
方法
a+s //连接
s.length //长度
var s="hehe" //定义
s.charAt(0) //第一个字符
s.substring(1,4)
s.slice(1,4)
s.slice(-3) //后三个字符
s.indexOf("I") //字符I最先出现的位置
s.lastIndexOf("i") //最后出现的位置
s.indexOf("i",3) //在位置3之后最先出现的
s.split(",") //分割
s.replace("h","H") //全文字符替换
s.toUpperCase() //全文字符替换
模式匹配
构造函数 RegExp() 创建模式匹配对象,称为正则表达式,并不是基本类型,只是具有实用API的特殊对象,两条斜线之间的文本构成了一个正则表达式直接量,第二条斜线之后也可以跟一个或多个字母,用来修饰匹配模式的含义,如 * /^HTML/ 匹配一html开始的字符串 * /[1-9][0-9]/ 匹配一个非零数字 * /\bjavascript\b/i 匹配单词'javascript' 忽略大小写
方法
var text="testing1,2,3"
var pattern=/\d+/g// //匹配所有包含一个或多个数字的实例
pattern.test(text) //返回true,匹配成功
test.search(pattern) //返回9,首次匹配成功的位置
text.match(pattern) //返回["1","2","3"],所有匹配组成的数组
text.replace(pattern) //返回“testing:#,#,#”
text.split(/\D+/) //返回["","1","2","3"] 用非数字字符截取字符串
boolean值
任何一个js值都可以转换成布尔值,下面这些会转成false:
- undefined
- null
- 0
- -0
- NaN
- "" 空字符串
if(o!=null)和if(o)等价
方法
toString() 转成"false"和true
null和undefined
null
null是一个关键字,表示一个特殊值,常用来描述"空值"
对null执行typeOf返回object,null是特殊的对象值,表示对象是“无值”的
undefined
表示值的空缺,用未定义的值表示更深层次的“空值”,查询对象属性或数组元素的值时返回undefined说明这个属性或元素不存在,typeOf返回undefined
联系和区别
- 都表示值的空缺,往往可以互换,==判断两者是相等的,===不等
- 都不包含任何属性和方法
- undefined表示系统级的、出乎意料的或类似错误的空缺
- null表示程序级的、正常的或在意料中的值的空缺 <!--/Note-->
全局对象
全局对象的属性是全局定义的符号,在js中可以直接使用,在解释器启动时,将创建新的全局对象,并给它一组定义的初始属性
全局属性
如undefined\Infinity\NaN
全局函数
如isNaN(),parseInt()
构造函数
如Date()\RegExp()\String()
全局对象
如Math和JSON
全局对象的初始属性并不是保留字,但他们应该当做保留字来对待
包装对象
.符号引用属性值,当属性是个函数时称其为方法 只要引用了字符串的属性,js就会将字符串通过调用new String(s)的方式转成对象,一旦属性引用结束,对象就被销毁
var s="test";
s.len=4;
var t=s.len;
t的值为undefined
存取字符串、数字或布尔值的属性时创建的临时对象称为包装对象,字符串、数字和布尔值的属性都是只读的
不可变的原始值和可变的对象引用
js中原始值是不可更改的,原始值的比较是值的比较 对象是可变的,对象的比较并非值的比较 对象值都是引用,对象的比较是引用的比较
类型转换
转换和相等性
显式类型转换
使用Boolean(),Number(),String()或者Object()方法 除了null或undefined都有toString()方法 Number类定义的toString()方法可以接受转换基数的可选参数,如
var n=17;
binary_string=n.toString(2)//转成二进制
octal_string="0"+n.toString(8)//转成八进制“021”
//toFixed()保留小数位数
var n=123456.789;
n.toFixed(0)//"1234567"
n.toFixed(2)//"123456.79"
n.toFixed(5)//"123456.78900"
n.toExponential(1)//"1.2e+5"
n.toExponential(3)//"1.23e+5"
n.toPrecision(4)//"1.235e+5"
n.toPrecision(7)//"123456.8"
-
Number()如果传入字符串,会试图将其转化成整数或浮点直接量,
-
ParseInt()只解析整数
-
ParseFloat()只解析浮点数和整数,如果前缀是0x,转成16进制,如果第一个非空格不是数字,返回NaN
-
ParseInt()可以接受第二个可选参数,是可选的基数
隐式类型转换
如某些运算符 ,+和!! x+""//等价于String(x) +x //等价于Number(x) !!x // 等价于Boolean(x)
对象转换为原始值
对象到布尔值
- 所有对象都会转成true
对象到字符串和数字
- 通过调用待转换对象的一个方法来完成
toString()
-
日期类返回一个可读的日期和时间字符串
-
RegExp类定义的toString()方法将RegExp对象转换成表示正则表达式直接量的字符串
-
如果对象没有toString()方法,或者这个方法并不返回一个原始值,会调用valueOf()方法,如果返回原始值,将这个值转成字符串,并返回这个字符串的结果,否则抛出类型错误异常
valueOf()
如果存在原始值,它就默认将对象转换成表示它的原始值复合值返回对象本身 日期类的valueOf()方法返回它的一个内部表示:从1970年1月1日来的毫秒数
-
在从对象到数字的过程中,js做了同样的事情,只是它会首先尝试valueOf()方法
-
数组继承了默认的valueOf()方法,这个方法返回一个对象而不是原始值,数组到数字的转换调用toString()方法,空字符串转成数字0,如果数组只包含一个数字元素,这个数字转成字符串,再转成数字
-
js中“+” 运算符可以进行数学加法和字符串连接操作,js使用特殊的方法将对象转换成原始值,“==”类似
-
对于所有非日期的对象来说,对象到原始值的转换基本上是对象到数字的转换(先调用valueOf()),日期则使用对象到字符串的转换模式,不会被强制转换成数字或字符串
-
“==”,“<”运算符也会完成对象到原始值的转换,都不会进一步转成数字或字符串
-
“+”“==”“!=”和关系运算符是唯一执行这种特殊的字符串到原始值的转换方式的运算符 “-”和其他则会直接转成数字
作为属性的变量
当声明了一个js全局变量时,实际上是定义了一个全局属性,给未声明的变量赋值,以这种方式创建的变量是全局对象的正常的可配值属性,并可以删除它们,声明了就不能删除
对于局部变量没有这个规定,局部变量可以当做跟函数调用相关的某个对象的属性
js允许使用this关键字来引用全局对象
函数作用域和声明提前
js的函数作用域指在函数内声明的所有变量在函数内始终可见,有意思的是,这意味着变量在声明之前甚至已经可用。这一特性被称为声明提前(hoisting)
在具有块级作用域的编程语言中,在狭小的作用域里让变量声明和使用变量的代码尽可能靠近彼此
变量作用域
变量声明
重复声明是合法且无害的,如果重复声明带有初始化器,和一条简单的赋值语句差不多
作用域链
全局变量在程序中始终是有定义的,局部变量在声明他的函数体内以及其所嵌套的函数内始终是有定义的
每一段js代码(全局代码或函数)都有一个与之关联的作用域链,这个作用域链是一个对象列表或链表,这组对象定义了这段代码“作用域”中的变量,当js需要查找x的值的时候(这一过程叫变量解析(variable resolution)),它会从链中的第一个对象开始查找,如果作用域上没有任何一个对象含有属性x,并最终抛出一个引用错误异常