ECMAScript5笔记
一、数据类型
6种数据类型
弱类型特性(类型转变、隐式转换 ...)
Number() x - 0 parseFloat() parseInt()
String() x + '' .toString()
Boolean() !! !
Object()
number string boolean null undefined object
隐式转换
+、- 、== ( NaN!=NaN )
包装对象(number string boolean)
number string boolean 以对象方式使用时会临时转换为对应的包装对象,使用完成后立即销毁
Object('abcd').slice(2, -1) === 'abcd'.slice(2, -1)
类型检测
Object.prototype.toString.call(x).slice(8, -1) //'Class'
typeof x //number | string | boolean | undefined | function | object
Array.isArray(x) //boolean
obj.constructor //类标识(实例的构造器),常常得手动添加
obj instanceof Class //boolean
数学计算
1.158.toFixed(2) //'1.16'
Math.round(1.158*100)/100 //1.16
Math.round() //去除小数点,四舍五入
Math.ceil() //去除小数点,向上取整
Math.floor() //去除小数点
parseInt() //智能转整(去除小数点)
parseFloat('41.2d21') //智能转浮(保留小数点)
Math.abs() //取绝对值
Math.random() //小于1大于或等0的随机数
Math.max(n1,nN)
Math.mix(n1,nN)
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) //求弦
Math.sqrt(Math.pow(length, 2) - Math.pow(x|y, 2)) //求勾或股
二、运算符
分类1:
一元
a++; a--/--a; a+=b; a-=b; //赋值(自加或减)
+str; -str; //正负极
!; //转成布尔并取反
!!; //转成布尔
二元
三元
?:
分类2:逻辑/比较 算术 赋值 ...
特殊:?: delete in typeof new ...
优先级:() > ?:/逻辑/比较 > 算术 > 赋值 ...
三、语句
try{} catch(ex){ throw ex } finally {}
函数声明 函数表达式 立即执行函数表达式
判断:switch(x) { case 5: break default: } ...
循环(遍历):for(var x in obj){} for(var i/j/k;isTrue;...){continue break} while(isTrue){continue break} do{continue break}while(isTrue)
'use strict':
delete不可配置的属性时报错
变量必须声明
函数直接调用时this指向undefined
安全:
arguments变为静态副本
eval有独立作用域
四、对象
字符串key
Object.keys({x:1,y:2}) //['x','y'] Object.keys([2,1,0]) //['0','1','2']
对象创建
字面量 new Class() Object.create(__proto__)
对象标签:
Objet.preventExtensions(obj) //不可添加新属性
Objet.isExtensible(obj)
Objet.seal(obj) //不可添加新属性,原有属性不可配置
Objet.isSealed(obj)
Objet.freeze(obj) //不可添加新属性,原有属性不可配置,原有属性不可写
Objet.isFrozen(obj)
属性操作
属性读写
异常处理:z=obj.y&&obj.y.z
属性删除
不能够delete:不可配置的属性、var变量(除了eval中的变量)、函数声明、形参
属性枚举:for(var x in obj){ obj.hasOwnProperty('x') }
属性标签
属性标签:writable configurable enumerable value get/set
标签配置:Object.defineProperty( obj, 'x', {value:8} ) --- defineProperty默认都是false,字面量默认都是true
Object.defineProperties( obj, { key1:{value:8},key2:{get:$.noop} } )
标签检测:Object.getOwnPropertyDescriptor(obj,'x') obj.propertyIsEnumerable('x')
get/set
{
get x(){},
set x(val){}
}
原型链中的get/set、原型链中的不可写属性 --- 在实例中无法用点语法重写该属性,只能用defineProperty
对象序列化
JSON.stringify(obj)
{val:undefined, a:NaN, b:Infinity, c:new Date()} --- '{"a":null, "b":null, "c":2016-05-25T22:32:10.910Z}'
toJSON
var obj = { o:{x:1,toJSON:function(){return this.x}} } --- JSON.stringify(obj) //'{"o":1}'
JSON.parse('{"x":1}') //{x:1}
其它对象方法
隐式转换时自动valueOf/toString
var valueOf = function(){return this.x}
'Result ' + {x:1,valueOf:valueOf} //'Result 1'
五、数组
概述
索引编号(key)
创建与操作
字面量 new Array(100) new Array(1,2,3) Array(100)
1 in [,,,,,] //false 2 in Array(100) //false
读写
var arr=[1,2,3]; delete arr[1]; arr.length //3
增删
arr[100]='kkk'; arr[100] //'kkk'; arr.length //101
arr.push('last-2','last-1'...) arr.pop() || arr.length -= 1
arr.unshift('first1','first2'...) arr.shift()
迭代
for(var i=arr.length-1;i>-1;i--){}
二维数组、稀疏数组
数组方法
join ------ 将数组转换为字符串并分隔
arr.join() arr.join('---')
字符串的重复:function repeatString(str, n){return Array(n+1).join(str)}
reverse(改) ------ 将数组反序
sort(改) ------ 排序
[b,a].sort() --- [a,b]
[2,10].sort() --- [10,2]
[10,2].sort(function(a,b){return a-b}) --- [2,10]
concat ------ 数组合并
arr.concat(4,5) //[arr,4,5]
arr.concat([4,5],[6],7) //[arr,4,5,6,7]
arr.concat([4,[5,6]]) //[arr,4,[5,6]]
slice ------ 提取数组片断
arr.slice( 起始索引, [结束索引] )
arr.slice(8) arr.slice(-4) arr.slice(8,-3)
splice(改) ------ 数组拼接(剪切、插入)
arr.splice(起始索引, 剪切数量, 插入的元素)
[0,1,2].splice(1) //[1,2] --- [0]
[0,1,2].splice(0,2) //[0,1] --- [2]
[0,1,2].splice(1,1,77,88,99) //[1] --- [0,77,88,99,2]
forEach (ES5) ------ 遍历
arr.forEach(function(el,i,arr){})
filter (ES5) ------ 过滤
arr.filter(function(el,i,arr){return true}) //[] return为真时才被选出
map (ES5) ------ 映射
arr.map(function(el,i,arr){return el+10}) //[]
every (ES5) ------ 数组判断(&&)
[1,10].every(function(el,i,arr){return el<5}) //false
some (ES5) ------ 数组判断(||)
[1,10].some(function(el,i,arr){return el<5}) //true
reduce/reduceRight (ES5) ------ 元素两两操作
arr.reduce(function(a,b){return a+b}) //求和、求最大值 ...
arr.reduce(function(a,b){return a+b},10)
indexOf/lastIndexOf (ES5) ------ 数组内检索
arr.indexOf(要检索的元素, 起始索引) //返回索引位置(找不到时返回-1)
[1,2,3,4].indexOf(1) //0
[1,2,3,4].indexOf(1,-3) //-1
Array.isArray (ES5) ------ 数组判断
字符串与数组
Array.prototype.join.call('abc', '---')
字符串同名方法:slice、indexOf/lastIndexOf
类数组转数组
Array.prototype.slice.call(obj, 0)
五、函数和作用域(函数、this)
概念
函数也是对象
foo.name = 函数名(函数被创建时的变量名,不可修改)
foo.length = 形参数量
foo.xxx = 自定义
函数返回值
普通调用:undefined
new调用:新建的实例(this)
函数声明
function foo(){} //被前置
函数表达式
var foo = function(){}
;(function(){})() / !function(){}() //立即执行函数表达式
函数this
func()
this === window || undefined('use strict'模式)
obj.func()
this === obj
原型链上方法
this === 实例
构造器new调用时
this === 新建的实例
call/apply
改变this
foo.call(obj,a,b)
foo.apply(obj,[a,b])
非'use strict'模式下:参数obj为unll或undefined时,则this指向window !!!
bind
改变this后返回新的函数(永久性绑定)
var foo2 = foo.bind(obj)
new foo.bind(obj) //this依然指向空对象(新建一实例)
柯里化
foo = function(x,y,z){}
var foo2 = foo.bind(null,x,y)
foo2(z)
函数属性/arguments
foo.name = 函数名(函数被创建时的变量名,不可修改)
foo.length = 形参数量
arguments.length = 实参数量
严格模式下:arguments变为静态副本
作用域
类型:全局作用域、函数作用域、eval作用域('use strict'才有独立作用域)
函数作用域:很好的封装私有变量
作用域链:由内向外访问
闭包--- 函数拥有被创建时的词法作用域,通过“返回、传参、赋值”的方式为外部所引用并调用
好处1:灵活、方便性
好处2:封装
处理不当:空间浪费、内存泄露
抽象概念
执行上下文/EC
EC类似栈,由外向内,再由内向外
变量对象VO、激活对象AO
变量初始化阶段:1、参数 2、函数声明(同名覆盖) 3、变量声明(同名跳过,初始值为undefined)
执行阶段:......
六、OOP
OOP概念
面向对象编程:继承/封装/多态、抽象类/实例
复用:私有静态/私有动态、公有动态/公有静态
继承(基于原型链)
原型属于抽象概念,但可以获取
Object.getPrototypeOf(obj)
obj.__proto__ //非标准属性
prototype
函数才有prototype
属性constructor指向构造器
bind返回的函数没有prototype (this已被改变,不用作类)
动态改变prototype = {x:888} (已有的实例不受影响)
动态改变prototype.x = 888; (已有的实例受影响)
例子:
//父类
var ParentClass = function(){
this.xxx = xxx
}
ParentClass.prototype.xxx = xxx
//子类
var SonClass = function(){
ParentClass.call(this) //'动态'继承到'动态'
this.xxx = xxx
}
//链接原型
SonClass.prototype = Object.create(ParentClass.prototype)
SonClass.prototype.constructor = SonClass
//只能用点语法添加'静态'
SonClass.prototype.xxx = xxx
instanceof
判断某实例是否属于某类
obj instanceof Object //obj的原型链上是否有Object.prototype
继承'动态'
父类.call(this) / 父类.apply(this)
继承原型
create
Student.prototype = Object.create(Person.prototype)
create兼容处理
if(!Object.create){
Object.create = function(proto){
function F (){};
F.prototype = proto;
return new F();
};
}
继承(原型链单继承)
封装(闭包)
多态(子类重写父类、模拟重载)
链式调用 (return this || xxx)
抽象类(复用的对象)
七、正则
参考:http://www.w3school.com.cn/jsref/jsref_obj_regexp.asp (百度 javascrip regexp)
元字符
. 任意字符(除换行符以外:\n、\r、\u2028、\u2029)
\d 数字
\D
\w 数字/字母/_
\W
\s 空格符/TAB、换行/回车
\S
\t、\n、\r
\b 单词边界(匹配单词)
\B
范围符号
[...] [a-z]、[0-5]、[a-zA-Z_0-9] 字符范围
[^...] [^a-z]、[^0-35-9]、[^abc] 字符范围以外
^ ^Hi 开头
$ test$ 结尾
?= test(?=xxx) 紧邻为
?! test(?!xxx) 紧邻非
分组
(x) /(abc)/.test('abc'); 分组,并记录,后续引用
(?:x) /(?:abc)(d)\1/.test('abcdd'); 仅分组,不记录,后续不引用
\n /(ab)(cd)-\2/.test('abcd-cd'); 引用前面的分组(索引从1开始)
重复
x*、x+ (贪婪匹配) n* 重复次数>=0 、 n+ 重复次数>0
x*?、x+? (?非贪婪匹配)
x? 出现0次或1次
x{n}、x{n,}、x{n,m} 重复n次、重复>=n次、重复次数为区间
x|y|z x或y或z
三个Flag
global、ignoreCase、multiline
/\w/gim
new RegExp('\\w', 'gim');
RegExp对象属性
var reg = /x/gm; reg.global; // true
var reg = /x/gm; reg.multiline; // true
var reg = /x/gm; reg.ignoreCase; // false
var reg = /x/gm; reg.source; //输出为字符串的正则内容,不带//也不带gim
var reg = /x/g; reg.lastIndex; //匹配时的起始位置(必须有g标志),被exec() || test()调用及设置,也可手动设置
RegExp对象方法
/5/gim.exec('5g55fd'); // ["5"] 只输出首个匹配
/5/gim.test('5g55fd'); // true
reg.toString(); //输出为字符串的正则内容,带//带gim
reg.compile('\w');
String对象方法
.trim()
.slice( start, [end] )
.substring( start, [end] ) --- [end]不能为负值
.substr( start, [length] )
.indexOf / lastIndexOf( 字符串, [起始索引] )
.search( 正则或字符串 ) --- 检索
.match( 正则或字符串 ) --- 检索,以数组方式返回
.replace( 正则或字符串, 字符串||function(match, $1, $2, ... key, str){return ...} )
.split( 正则或字符串, [数组的最大长度] )
.toLowerCase() --- 转小写
.toUpperCase() --- 转大写
'b'.localeCompare('c') //1|-1 --- 字母大小比较
'b' < 'c' //true