阅读笔记《JavaScript高级程序设计》
0. 严格模式
"user strict"
(1整个脚本顶部,2函数体顶部)
1. 数据类型
undefined -- 未定义
boolean
string
number
object -- 对象 或 null
function
0) typeof操作符(不是函数)
alert(val) //error
typeof val //返回"undefined"
val定义局部变量(函数体内),全局变量(不再任何函数体内)
直接写变量名定义全局变量
1) Undefined
所有未初始化的变量均为Undefined类型,值为undefined
undefined 派生自 null, null == undefined // true
typeof null; // "object"
2) Boolean
可以通过Boolean()函数将所有其它值转换为Boolean类型
转换为false的值有:"", 0和NaN, null, undefined
在控制流if()中科自动执行相应的Boolean转换
3) Number
十进制
八进制(0开头+(0-7),超过7则忽略开头的0,当做十进制)
十六进制(0x开头+(0-9及A-F/a-f))
浮点数(var num = 10.1; var num = 10.1e7), 注意浮点数是有误差的,比较式不要直接==
范围: Number.MAX_VALUE Number.MIN_VALUE, 超出范围为 -Infinity/Infinity(正/负无穷), isFinite()判断是否未超出范围
NaN (Not a Number)
将非数字字符串转换为Number返回NaN), 0除以0返回NaN, 正数/0返回Infinity, 任何NaN参与的算术运算值都为NaN
NaN不等于任何值(包括自己)
isNaN()
Number() --- Number("adf")NaN, Number(0011)11, Number(true)1
parseInt() --- parseInt("1234as")1234, parseInt("0xf")15
parseFloat() --- parseFloat(12.21.5)12.21, parseFloat(3.1e1)==31
4) string
"a" + "b" === "ab"
Number.toString()
String()
String(true) === "true"
String(null) === "null"
val test; String(test) === "undefined"
5) Object
和Java的Object类似
2. 操作符
- 单目运算符: ++ -- + - (即正负号)
- 位运算符: ~ & | ^ << >>(有符号右移,符号位不动) >>>
- 逻辑运算符: ! && ||
- 算术运算符: * / % + -
- 关系操作符: < > <= >= != == ===(全等,比较时不会做类型转换)
- 条件操作符: ? :
- 赋值操作符: = *= /= %= += -= <<= >>= >>>=
- 逗号操作符: , (返回值会最后一项,如:val a = 10, 9, 0; // a == 0)
3. 语句
- if () {} else {}
- do{} while();
- while() {}
- for(;😉 {}
- for( in ) {}
- break, continue, 标签 (标签语句用于break/continue退出多重循环)
- with (类似命名空间,大量使用影响性能,不建议使用)
- switch() {case: break; default:}}
- function () {}
4. 内存
1) 类型
- 除了对象是引用类型,其余的全是基础类型(赋值时为值拷贝,包括字符串)
- 类型检测instanceof
2) 作用域
- 变量名向上搜索的作用域链
- 只有全局作用域 和 函数作用域,没有块作用域(如:if和for语句块{}中定义的局部变量,在语句块结束之后还能使用,这些局部变量属于当前函数作用域)
3) 垃圾收集
- 标记清除(普遍使用) 和 引用计数(循环引用会造成内存泄露,不再使用)
5. 引用类型
1) Object
类似lua的table
val obj = new Object(); === val obj = {};
2) Array
- 下标从0开始
- val arr = new Array(); === val arr = [];
- Array.length ---> 获取个数
- Array.isArray(valName) ---> 检测valName是否是Array
- Array.join(",") ---> 用,分隔、
栈方法
Array.push(), Array.pop()
队列方法
Array.shift()(获取队首), Array.push(), Array.unshift()(从队首放入)
排序
Array.reverse() --- 逆序
Array.sort(sortFunc)
数组操作方法
concat() --- 使用当前数据 + 输入参数创建一个新的数组
slice(1,4) --- 创建一个新的子数组 [1,4)
splice() --- 不会创建新数组。1.删除(splice(0,2)从位置0开始删除2项) 2.插入(splice(2,0,"red")从位置2插入"red") 3.替换(splice(2,1,"red")删除位置2这一项,并在位置2插入"red")
位置方法
Array.indexOf(4) --- 返回数组位置4的项
Array.lastIndexOf(1)
迭代方法
every()
filter()
forEach()
map()
some()
归并方法
reduce()
reduceRight()
3) Date
var now = new Date() --- 返回当前时间(距离1970/1/1的时间)
1) 通过字符串获取时间
Date.parse("1/13/2004") Date.parse("2015-6-9T00:00:00")
Date.UTC()
2) 格式化
toDateString()
toTimeString()
toLocaleDateString()
toLocaleTimeString()
toUTCString()
3) 常用方法
getTime() --- 获取毫秒数 P102
4) RegExp
正则表达式
5) Function
与lua的function类似,函数的名字仅仅只是一个包含指针的变量而已
- 每个函数内有两个特殊对象 arguments(存放参数列表的数组对象) 和 this(this引用的是当前作用域)
- 每个函数内有两个非继承而来的方法:apply(), call()
6) 包装类型
Boolen, Number, String
基本类型在读取模式下,后台就会做特殊处理:
(1) 创建基本类型的包装实例;
(2) 在实例上调用制定的方法;
(3) 销毁这个实例。
所以对于包装类型,一句代码的开始时创建,结束时销毁。例:
var s = "something";
s.color = "red"; //(1)包装类型String创建 (2)添加color属性 (3)包装类型销毁
alert(s.color); // undefined
7) 单体内置对象
Global, Math
TODO:
6. 对象
1) 定义属性
[[Configurable]] [[Enumerable]] [[Writable]] [[Value]]
defineProperty()
2) 创建对象
(1) 工厂模式:全是Object对象,无法识别具体对象类型
(2) 构造函数模式:每一个对象有一份自己的成员函数,难道使用全局函数?
(3) 原型模式:1.不能传递初始化构造参数;2.如果属性中有引用类型,会在多个对象中共享。
(4) 组合使用构造函数模式和原型模式:广泛使用(函数和constructor使用prototype原型模式,属性使用构造函数模式)
(5) 动态原型模式:构造函数模式中,对函数进行if判断,没有还会创建。
(6) 寄生构造函数模式:
(7) 稳妥构造函数模式:
3) 继承
基于对象原型的继承
7. 函数表达式
递归函数应始终使用arguments.callee来递归调用本身,而不是使用函数名(函数名可能会发生变化)
在函数内部定义了其它函数,就创建了闭包