ES5学习
1、概要
-
轻量级脚本语言(不能开发OS,只控制其他大型program)
-
嵌入式语言(JS无I/O相关API,靠host提供)
-
JavaScript核心语法:基本的语法构造和标准库
-
使用领域:浏览器、Node、数据库操作、移动平台、内嵌脚本语言(GNOME3)、跨平台桌面应用
-
性能强大:适合异步编程、支持编译后运行、事件驱动和非阻塞式设计
2、JavaScript基本语法
1.语句
-
js程序执行单位(行)
-
语句结束标志(;)
2.变量
-
变量是对‘值’的具名引用
-
变量名区分大小写
-
不写var创建全局变量
-
JavaScript是一种动态类型语言
-
变量提升
3.标识符
-
标识符命名规则(Unicode字母、$、_和数字,数字不能打头)
-
中文是合法的标识符
-
js保留字不能作标识符
4.注释
-
单行注释(//)
-
多行注释(/* 代码 */)
5.区块
-
{}连通其中的语句,称为block
-
block不构成单独的scope
6.条件语句
-
if语句
-
switch语句
-
三元运算符(??(if…else…的简写形式)
7.循环语句
-
while语句
-
for循环
-
do…while循环
-
break语句(用于跳出代码块或循环)
-
continue语句(用于立即终止本轮循环,开始下一轮循环)
-
break和continue都只针对最内层循环
-
标签label(通常与break和continue配合使用,跳出多重循环或代码块)
2、数据类型
1.简介
-
ES5六种数据类型(number、string、boolean、undefined、null、object)
-
狭义的对象、数组、函数是对象的三个子类型
-
确定值的类型三种方法:typeof运算符、instanceof运算符、object.prototype.toString方法
-
typeof运算符结果:number、string、boolean、object、function、undefined
-
instanceof运算符可以区分数组和对象
2.null、undefined和布尔值
-
null和undefined都可以表示“没有”
-
null的存在是95年js诞生历史遗留问题
-
null表示‘空’的对象,转数值时为0;undefined表示‘无定义’的原始值,转数值为NaN
-
会被转换为false的值:undefined、null、false、0、NaN、“”或‘’(空字符串)
3.数值
-
JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此
-
0.1+0.2!==0.3类似的精度问题,容易产生隐藏的bug
-
如果一个数大于等于2的1024次方,那么就会发生“正向溢出”,返回Infinity; 如果一个数小于等于2的-1075次方,那么就会发生为“负向溢出”,这时会直接返回0
-
科学计数法:-3.1E-12(e和E皆可)
-
十进制:没有前导0的数值。
-
八进制:有前缀0o或0O(Octal)的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。
-
十六进制:有前缀0x或0X(Hex)的数值。
-
二进制:有前缀0b或0B(binary)的数值。
-
特殊数值:+0和-0、NaN(Not a Number,NaN不等于任何值,包括它本身)、Infinity
-
parseInt():用于将字符串转为整数,非字符串会先转换为字符串再转为整数;逐字符转换,遇到不能转换的就先返回转好的部分,如果第一个字符都不能转(后面跟着数字的正负号除外)则返回NaN);接受第二个参数,可用于进制转换;转换结果都是十进制或者NaN
-
parseFloat():用于将字符串转为浮点数,逐字符转换;转换结果都是浮点数或者NaN
-
isNaN():返回一个布尔值,用来判断一个值是否为NaN
-
isFinite():返回一个布尔值,表示某个值是否为正常的数值。
4.字符串
-
''和""皆可,并且相互可嵌套
-
多行字符串
var longString = 'Long \
long \
long \
string';
-
连接运算符(+)
-
字符串可以用[]运算符来访问单个字符
-
length属性返回字符串长度
-
js使用Unicode字符集
-
Base64编码(转换ASCII中无法打印的符号,以文本格式传递二进制数据)
-
所谓 Base64 就是一种编码方法,可以将任意值转成 0~9、A~Z、a-z、+和/这64个字符组成的可打印字符。使用它的主要目的,不是为了加密,而是为了不出现特殊字符,简化程序的处理
-
原生Base64和ASCII转码方法:btoa()任意值转为Base64编码;atob() Base64编码转为原来的值
-
非ASCII码转Base64:
btoa(encodeURIComponent(str));
decodeURIComponent(atob(str));
5.对象
-
简单说,对象就是一组“键值对”(key-value)的集合,用{}来定义
-
对象的所有键名都是字符串,如果键名是数值,会被自动转为字符串。
-
动态属性
-
对象的变量名是对这个对象的引用(用指针定义)
-
对于
{ foo:123 }
编译器产生歧义的解决办法:编译器一律解释为代码块(如果要解释为对象需用‘()’包裹,因为圆括号里面只能是表达式) -
读取对象属性和对象属性赋值的两种方法:
obj.p or obj['p']
-
Object.keys()方法查看一个对象本身的所有属性
-
使用delete命令删除对象属性,当delete删除一个不存在的属性时也返回true
-
in运算符:用于检查对象是否包含某个属性(注意,检查的是键名,不是键值)
-
使用for…in遍历对象的属性(遍历可遍历的属性,还遍历继承属性)
-
with语句:用于操作同一个对象的多个属性时,提供一些书写的方便。并不改变作用域,反而造成代码优化二义性,不建议使用
6.函数
-
函数定义的三种方式 :function命令、函数表达式、new Function(‘param1’, ‘param2’…, ‘body’);
-
函数重复申明不会报错,只会覆盖
-
函数可以调用自身,这就是递归(recursion)
-
函数名的提升,函数表达式定义的变量提升
-
name属性:返回函数的名字
-
length属性:返回函数预期传入的参数个数,即函数定义之中的参数个数
-
toString():返回一个字符串,内容是函数的源码
-
ES5的两种作用域(scope):全局作用域和函数作用域
-
函数内部的变量提升
-
js允许函数调用省略参数,值为undefined
-
函数的传值调用和传引用调用
-
同名参数后面覆盖前面
-
arguments对象包含了函数运行时的所有参数,是一种类数组对象,用[]访问参数
-
闭包:简单理解成“定义在一个函数内部的函数”
-
闭包的用处:在函数调用完成后继续保留内部信息,读取函数内部信息,封装对象的私有属性和私有方法
-
函数立即调用表达式(IIFE)
-
解决eval()带来的安全性问题:严格模式下,eval内部不会影响到外部作用域
7.数组
-
本质上,数组属于一种特殊的对象。typeof运算符会返回数组的类型是object,in操作符和for…in循环都可以用
-
length属性:返回数组的成员数量,是可写的
-
数组可以有空位,值为undefined,遍历数组时空位会被跳过
-
类似数组的对象:arguments对象、大多数的DOM元素集和字符串,通过call()方法可以使用数组的某些方法(
Array.prototype.forEach.call(arrayLike,...)
3、运算符
1、算术运算符
-
JavaScript的10种算术运算符:加减乘除(x+y、x-y、x*y、x/y)、指数运算符(x ** y)、余数运算符(x%y)、自增自减运算符(++x或x++、–x或x–)、数值运算符(+x)、负数值运算符(-x)
-
加法运算符的重载
-
对象作为运算子做加法,先调用对象的valueof(),若返回的不是原始类型值,则继续调用toString(),由此可以做运算符重载
-
负数做余数运算要使用绝对值函数
-
数值运算符和非数值运算符的作用在于可以将任何值转为数值(与Number函数的作用相同)
-
指数运算符前一个运算子是底数,后一个运算子是指数,指数运算符是右结合
-
赋值运算符可以结合其他运算符形成变体(x+=y、x**=y…)
2、比较运算符
-
JavaScript提供8个比较运算符:>、<、<=、>=、、=、!=、!==
-
字符串的比较会比较首字符的Unicode码点,对象的比较会转换为原始类型值进行比较(valueof())
-
复合类型进行严等判断时,比较的是它们指向的地址是否一样
-
null和undefined,与自身严格相等,相互之间不严格相等
3、布尔运算符
-
四个布尔运算符:!、&&、||、?:
-
只通过第一个表达式的值,控制是否运行第二个表达式的机制,就称为**“短路”**,可以取代 if 结构
-
三元条件表达式是表达式,必须出现在期望出现表达式的场合
4、二进制位运算符
-
7个二进制位运算符:|(or)、&(and)、~(not)、^(xor)、<<、>>、>>>
-
异或运算的特殊运用(交换两个变量值):
a^=b,b^=a,a^=b
-
位运算符可以用作设置对象属性的开关
5、其他运算符
-
void运算符的作用是执行一个表达式,然后不返回任何值,或者说返回undefined,其优先级很高,建议使用()。例如:
void(0)
<a href="javascript: void(document.form.submit())">提交</a>
-
逗号运算符用于对两个表达式求值,并返回后一个表达式的值(在返回一个值之前,进行一些辅助操作)
PS:delete命令###
-
delete用来删除一个对象的属性(包括全局变量、数组元素)
-
可以删除隐式全局变量,但不可已删除显示全局变量。全局变量其实是global对象(window)的属性
-
内置对象的内置属性不能被删除,用户自定义的属性可以被删除
-
不能删除一个对象从原型继承而来的属性,但是可以直接从原型上删掉它;
-
当删除数组元素时,数组的长度并不会变小,会产生空位
4、语法
1、数据类型转换
-
JavaScript是动态类型语言,当数据类型与编译器预期不符,则进行自动类型转换
-
强制转换:Number()、String()、Boolean()三种方法
-
Number()如果有一个字符不能转换数值则转换结果为NaN,parseInt()是尽力能转多少转多少,Number()遇到参数是对象直接NaN
-
String()方法将任意类型的值转化成字符串,例如:
String(true) //结果为"true",undefined和null一样
String({a:1}) //"[object Object]"
String([1,2,3]) //"1,2,3"
-
Boolean()函数只有5个值会转换为false:undefined、null、-0或+0、NaN、’’
2、错误处理机制
-
Error对象,包含三个属性:message、name、stack
-
Error派生的6个原生错误对象:
SyntaxError对象:语法错误
ReferenceError对象:指针错误
RangeError对象:值超出有效范围
TypeError 对象:变量或参数不是预期类型
URIError对象:URI 相关函数的参数不正确(主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数)
EvalError对象:eval函数没有被正确执行
-
try…catch结构
try{
throw new Error('出错了');
}catch(e){
console.log("执行catch的结束语句"); //此句不会执行
}finally{
console.log("程序执行完毕");}
3、console对象与控制台
-
console对象静态方法:console.log()、console.info()、console.debug()、console.warn()、console.error()、console.table()(将对象或数组转换为表格显示)、console.count()、console.dirxml()(用于以目录树的形式,显示 DOM 节点)
console.dir()(对一个对象进行检查(inspect),并以易于阅读和打印的格式显示)、
console.assert(断言判断布尔值,断言)(程序运行过程中,进行条件判断)
console.time(),console.timeEnd()(算出一个操作所花费的准确时间)等
-
debugger语句:设置断点,当代码运行到debugger语句时,就会暂停运行
5、标准库
1、Object对象
-
Object( none / param )
-
new Object( none / param)
-
Object的静态方法
遍历相关: Object.keys(对象),返回可枚举属性组成的数组 Object.getOwnPropertyNames(对象),返回所有属性组成的数组 对象属性模型的相关: Object.getOwnPropertyDescriptor():获取某个属性的描述对象 Object.defineProperty():通过描述对象,定义某个属性 Object.defineProperties():通过描述对象,定义多个属性 控制对象状态: Object.preventExtensions():防止对象扩展 Object.isExtensible():判断对象是否可扩展 Object.seal():禁止对象配置 Object.isSealed():判断一个对象是否可配置 Object.freeze():冻结一个对象 Object.isFrozen():判断一个对象是否被冻结 原型链相关 Object.create():该方法可以指定原型对象和属性,返回一个新的对象 Object.getPrototypeOf():获取对象的Prototype对象 拷贝属性 Object.assign():将所有可枚举属性的值从一个或多个源对象复制到目标对象,返回目标对象。
-
Object的实例方法
Object.prototype.valueOf():返回当前对象对应的值 Object.prototype.toString():返回当前对象对应的字符串形式 Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式 Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性 Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型 Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举 Object.prototype.valueOf():返回一个对象的“值”,默认情况下返回对象本身 Object.prototype.toString():返回一个对象的字符串形式,默认情况下返回类型字符串 Object.prototype.toLocaleString():与toString()相同,主要是留出一个接口,让各种不同的对象实现自己版本的toLocaleString Object.prototype.hasOwnProperty():受一个字符串作为参数,返回一个布尔值,表示该实例对象自身是否具有该属性。
-
不同数据类型的Object.prototype.toString方法返回值如下:
数值: 返回[object Number]。 字符串: 返回[object String]。 布尔值: 返回[object Boolean]。 undefined: 返回[object Undefined]。 null: 返回[object Null]。 数组: 返回[object Array]。 arguments 对象:返回[object Arguments]。 函数: 返回[object Function]。 Error 对象: 返回[object Error]。 Date 对象: 返回[object Date]。 RegExp 对象: 返回[object RegExp]。 其他对象: 返回[object Object]。
2、属性描述对象
-
属性描述对象提供6个元属性:value、writable、enumerable、configurable、get、set
{ value: 123, //默认:undefined writable: false, //默认:true enumerable: true, //默认:true configurable: false, //默认:true get: undefined, //默认:undefined set: undefined //默认:undefined }
3、Array对象
-
构造函数
Array(数组大小) or new Array(数组大小)
-
静态方法
Array.isArray() :返回boolean值,弥补typeof不能识别数组的不足
-
实例方法
valueOf():所有对象都拥有的方法,数组的valueOf方法返回数组本身 toString():是对象的通用方法,数组的toString方法返回数组的字符串形式 @push():在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度 @pop():删除数组的最后一个元素,并返回该元素 @shift():删除数组的第一个元素,并返回该元素 @unshift():在数组的第一个位置添加元素,并返回添加新元素后的数组长度 join():以指定参数作为分隔符,将所有数组成员连接为一个字符串返回 concat():将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变,数组中有对象进行浅拷贝 @reverse():颠倒排列数组元素,返回改变后的数组 slice():提取目标数组的一部分,返回一个新数组,原数组不变。 @splice():删除原数组的一部分成员,并可以在删除的位置添加新的数组成员 @sort():对数组成员进行排序,默认是按照字典顺序排序 map():将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回 @forEach():对数组的所有成员依次执行参数函数,不返回值 filter():过滤数组成员 some():只要一个成员的返回值是true,则整个some方法的返回值就是true every():所有成员的返回值都是true,整个every方法才返回true reduce():从左到右依次处理数组的每个成员,最终累计为一个值 reduceRight():从右到左依次处理数组的每个成员,最终累计为一个值 indexOf():返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1 lastIndexOf():返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1
4、包装对象
-
所谓“包装对象”,就是分别与数值、字符串、布尔值相对应的Number、String、Boolean三个原生对象。
-
三种包装对象都具有valueOf()和toString()方法
-
原始类型的值,可以自动当作包装对象调用,即调用包装对象的属性和方法。这时,JavaScript 引擎会自动将原始类型的值转为包装对象实例,在使用后立刻销毁实例。
5、Number对象
Number.prototype.toString():将一个数值转为字符串形式,接受一个参数,表示输出的进制
Number.prototype.toFixed():先将一个数转为指定位数的小数,然后返回这个小数对应的字符串
Number.prototype.toExponential():将一个数转为科学计数法形式
Number.prototype.toPrecision():将一个数转为指定位数的有效数字
6、String对象
String对象是一个类似数组的对象
-
静态方法
String.fromCharCode():参数是一个或多个数值,代表 Unicode 码点,返回值是这些码点组成的字符串。
-
实例方法
String.prototype.charAt():返回指定位置的字符,参数是从0开始编号的位置 String.prototype.charCodeAt():返回字符串指定位置的 Unicode 码点(十进制表示) String.prototype.concat():连接两个字符串,返回一个新字符串,不改变原字符串 String.prototype.slice():从原字符串取出子字符串并返回,不改变原字符串 String.prototype.substr():从原字符串取出子字符串并返回,不改变原字符串 String.prototype.indexOf():确定一个字符串在另一个字符串中第一次出现的位置 String.prototype.lastIndexOf():从尾部开始匹配,确定一个字符串在另一个字符串中第一次出现的位置 String.prototype.trim():去除字符串两端的空格,返回一个新字符串,不改变原字符串 String.prototype.toLowerCase():将一个字符串全部转为小写 String.prototype.toUpperCase():一个字符串全部转为大写 String.prototype.match():确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的第一个字符串 String.prototype.search():返回值为匹配的第一个位置 String.prototype.replace():替换匹配的子字符串,一般情况下只替换第一个匹配(除非使用带有g修饰符的正则表达式) String.prototype.split():按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组 String.prototype.localeCompare():比较两个字符串
7、Math对象
-
静态属性:Math.E、Math.LN2(2的自然对数)、Math.LN10(10的自然对数)、Math.LOG2E(以2为底的e的对数)、Math.LOG10E(以10为底的e的对数)、Math.PI、Math.SQRT1_2(0.5的平方根)、Math.SQRT2(2的平方根)
-
静态方法
Math.abs():绝对值 Math.ceil():向上取整 Math.floor():向下取整 Math.max():最大值 Math.min():最小值 Math.pow():指数运算 Math.sqrt():平方根 Math.log():自然对数 Math.exp():e的指数 Math.round():四舍五入 Math.random():随机数 Math.sin():返回参数的正弦(参数为弧度值) Math.cos():返回参数的余弦(参数为弧度值) Math.tan():返回参数的正切(参数为弧度值) Math.asin():返回参数的反正弦(返回值为弧度值) Math.acos():返回参数的反余弦(返回值为弧度值) Math.atan():返回参数的反正切(返回值为弧度值)
8、Date对象
-
普通函数的用法:Date对象可以作为普通函数直接调用,不管有没有参数,都是返回当前时间
-
构造函数的用法:new Date(),默认调用的是toString(),参数有多种形式,除了年和日,其他参数都是计算机计数(从0开始)
-
Date实例转为数值,等于对应的毫秒数
-
静态方法
Date.now():返回当前时间距离时间零点(1970年1月1日 00:00:00 UTC)的毫秒数 Date.parse():解析日期字符串,返回该时间距离时间零点(1970年1月1日 00:00:00)的毫秒数 Date.UTC():接受年、月、日等变量作为参数,返回该时间距离时间零点(1970年1月1日 00:00:00 UTC)的毫秒数
-
实例方法
to类: Date.prototype.valueOf():返回实例对象距离时间零点(1970年1月1日00:00:00 UTC)对应的毫秒数 Date.prototype.getTime():返回实例对象距离时间零点(1970年1月1日00:00:00 UTC)对应的毫秒数 Date.prototype.toString():返回一个完整的日期字符串 Date.prototype.toUTCString():返回对应的 UTC 时间,也就是比北京时间晚8个小时 Date.prototype.toISOString():返回对应时间的 ISO8601 写法 Date.prototype.toJSON():返回一个符合 JSON 格式的 ISO 日期字符串,与toISOString方法的返回结果完全相同 Date.prototype.toDateString():返回日期字符串(不含小时、分和秒) Date.prototype.toTimeString():返回时间字符串(不含年月日) get类(每个方法都有getUTC*版): getTime():返回实例距离1970年1月1日00:00:00的毫秒数 getDate():返回实例对象对应每个月的几号(从1开始) getDay():返回星期几,星期日为0,星期一为1,以此类推 getFullYear():返回四位的年份 getMonth():返回月份(0表示1月,11表示12月) getHours():返回小时(0-23) getMilliseconds():返回毫秒(0-999) getMinutes():返回分钟(0-59) getSeconds():返回秒(0-59) getTimezoneOffset():返回当前时间与 UTC 的时区差异,以分钟表示,返回结果考虑到了夏令时因素 set类(也有对应的UTC版): setDate(date):设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳。 setFullYear(year [, month, date]):设置四位年份。 setHours(hour [, min, sec, ms]):设置小时(0-23)。 setMilliseconds():设置毫秒(0-999)。 setMinutes(min [, sec, ms]):设置分钟(0-59)。 setMonth(month [, date]):设置月份(0-11)。 setSeconds(sec [, ms]):设置秒(0-59)。 setTime(milliseconds):设置毫秒时间戳。
9、RegExp对象
-
建立正则表达式的两种方式:字面量创建和使用RegExp构造函数
var regex=new RegExp('xyz','i');
var regex=/xyz/i
-
实例属性
RegExp.prototype.ignoreCase:返回一个布尔值,表示是否设置了i修饰符。 RegExp.prototype.global:返回一个布尔值,表示是否设置了g修饰符。 RegExp.prototype.multiline:返回一个布尔值,表示是否设置了m修饰符。 RegExp.prototype.lastIndex:返回一个整数,表示下一次开始搜索的位置。该属性可读写,但是只在进行连续搜索时有意义,详细介绍请看后文。 RegExp.prototype.source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。
-
实例方法
RegExp.prototype.test():返回一个布尔值,表示当前模式是否能匹配参数字符串 RegExp.prototype.exec():返回匹配结果。如果发现匹配,就返回一个数组(含有input、index属性),成员是匹配成功的子字符串,否则返回null 字符串的实例方法: String.prototype.match():返回一个数组,成员是所有匹配的子字符串。 String.prototype.search():按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。 String.prototype.replace():按照给定的正则表达式进行替换,返回替换后的字符串,可以获取组匹配变量 String.prototype.split():按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。
-
匹配规则
' . ':匹配除回车(\r)、换行(\n) 、行分隔符(\u2028)和段分隔符(\u2029)以外的所有字符 ' ^ ':表示字符串的开始位置 ' $ ':表示字符串的结束位置 ' | ':表示“或关系”(OR),即cat|dog表示匹配cat或dog ' \ ':转义符,转换特殊含义的元字符为普通字符 字符类 ' [] ':字符类,表示有一系列字符可供选择,只要匹配其中一个就可以了 ' ^ ':脱字符,如果方括号内的第一个字符是[^],则表示除了字符类之中的字符,其他字符都可以匹配 ' - ':连字符,对于连续序列的字符,连字符(-)用来提供简写形式 预定义模式 \d 匹配0-9之间的任一数字,相当于[0-9]。 \D 匹配所有0-9以外的字符,相当于[^0-9]。 \w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]。 \W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]。 \s 匹配空格(包括换行符、制表符、空格符等),相等于[ \t\r\n\v\f]。 \S 匹配非空格的字符,相当于[^ \t\r\n\v\f]。 \b 匹配词的边界。 \B 匹配非词边界,即在词的内部。 重复类 {n}:表示恰好重复n次 {n,}:表示至少重复n次 {n,m}表示重复不少于n次,不多于m次 量词符 ? 问号表示某个模式出现0次或1次,等同于{0, 1}。 * 星号表示某个模式出现0次或多次,等同于{0,}。 + 加号表示某个模式出现1次或多次,等同于{1,}。 非贪婪模式(尽可能匹配得更多,多在全局模式下用) +?:表示某个模式出现1次或多次,匹配时采用非贪婪模式。 *?:表示某个模式出现0次或多次,匹配时采用非贪婪模式。 ??:表格某个模式出现0次或1次,匹配时采用非贪婪模式。 修饰符 g:g修饰符表示全局匹配(global),加上它以后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换 i:忽略大小写(ignoreCase) m:表示多行模式(multiline),会修改^和$的行为,即^和$会识别换行符(\n)从而跳过它 组匹配 ():括号表示分组匹配,括号中的模式可以用来匹配分组的内容 (?:x):非捕获组(Non-capturing group),表示不返回该组匹配的内容,即匹配的结果中不计入这个括号 x(?=y):先行断言(Positive look-ahead),x只有在y前面才匹配,y不会被计入返回结果 x(?!y):先行否定断言(Negative look-ahead),x只有不在y前面才匹配,y不会被计入返回结果
10、JSON对象
-
JSON(JavaScript Object Notation)是一种数据交换的文本格式,目的是取代XML格式
-
JSON优点:简单、符合 JavaScript 原生语法
-
组成规则
复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象。 原始类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)。 字符串必须使用双引号表示,不能使用单引号。 对象的键名必须放在双引号里面。 数组或对象最后一个成员的后面,不能加逗号。
-
JSON原生对象的静态方法
JSON.stringify():将一个值转为 JSON 字符串,第二个可选参数是对象属性白名单,第三个可选参数是设置格式。修改toJSON()方法去重载此方法。
JSON.parse():将 JSON 字符串转换成对应的值
6、JavaScript面向对象
1、实例对象与new命令
-
JavaScript 语言的对象体系,不是基于“类”的,而是基于构造函数(constructor)和原型链(prototype)。
-
构造函数的特点:
函数体内部使用了this关键字,代表了所要生成的对象实例。 生成对象的时候,必须使用new命令。
-
new命令执行时,构造 函数内部的 this 和prototype
2、this关键字
-
简单说,this就是属性或方法“当前”所在的对象。只要函数被赋给另一个变量,this的指向就会变为另一个变量运行时所在对象
-
原始的对象以字典结构保存,如果属性值为函数,那么保存的是函数的地址。this的设计目的就是在函数体内部,指代函数当前的运行环境。
{ foo: { [[value]]: 函数的地址 [[writable]]: true [[enumerable]]: true [[configurable]]: true } }
-
使用场合
全局环境使用this,它指的就是顶层对象window。 构造函数中的this,指的是实例对象。 对象的方法里面包含this,this的指向就是方法运行时所在的对象
-
多层this的指向可能不明确,嵌套函数中,内层函数的this指针指向的就是全局对象
-
尽量避免回调函数的this,尤其在DOM操作时,ES6的箭头函数解决了这个问题
-
绑定this的方法
Function.prototype.call():参数是this要绑定的对象 Function.prototype.apply():和call()方法的区别是参数不同 Function.prototype.bind():将函数体内的this绑定到某个对象,然后返回一个绑定后的新函数
3、JavaScript 的原型链继承
-
构造函数的缺点:同一个构造函数的多个实例之间,无法共享属性,从而造成对系统资源的浪费。解决办法是 JavaScript 的原型对象(prototype)
-
JavaScript 规定,每个函数都有一个prototype属性,指向一个对象。构造函数生成实例时,该属性会自动成为实例对象的原型
-
原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上。
-
原型对象的作用,就是定义所有实例对象共享的属性和方法
-
依据原型链上溯最终都可以到Object.prototype,而Object.prototype的原型是null,原型链的尽头就是null
-
读取对象属性时,会沿着原型链向上找,直到找到为止,如果没找到返回undefined
-
如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做**“覆盖”(overriding)**。
-
Object.prototype.constructor的作用是可以得知实例对象的构造函数
-
修改原型对象时,一般要同时修改constructor属性的指向。
-
instanceof 运算符返回一个布尔值,表示对象是否为某个构造函数的实例
v instanceof Vehicle // 等同于 Vehicle.prototype.isPrototypeOf(v)
-
instanceof的原理是检查右边构造函数的prototype属性,是否在左边对象的原型链上
-
一个构造函数继承另一个构造函数的办法
Super和Sub分别是父类构造函数和子类构造函数 第一种写法: function Sub(value) { Super.call(this); this.prop = value; } Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub; Sub.prototype.method = '...'; 第二种写法(不推荐): Sub.prototype=new Super(); //会造成子类拥有父类实例的方法
-
可以通过Object.assign()实现多重继承
4、JavaScript的模块化
-
JavaScript 不是一种模块化编程语言,ES6 才开始支持“类”和“模块”
-
模块化的实现
基本写法(IIFE写法): var module1 = (function () { var _count = 0; var m1 = function () { //... }; var m2 = function () { //... }; return { m1 : m1, m2 : m2 }; })(); 模块的放大模式(需拆分或者继承模块) var module1 = (function (mod){ mod.m3 = function () { //... }; return mod; })(module1); 模块的宽放大模式 var module1 = (function (mod) { //... return mod; })(window.module1 || {});
3.输入全局变量
IIFE可以输入全局变量,还可以起到命名空间的作用
(function($, window, document) {
function go(num) {
}
function handleEvents() {
}
function initialize() {
}
function dieCarouselDie() {
}
//attach to the global scope
window.finalCarousel = {
init : initialize, //模块的接口
destroy : dieCarouselDie //模块的接口
}
})( jQuery, window, document )
5、Object对象处理的相关方法
-
静态方法
Object.getPrototypeOf():返回参数对象的原型 Object.setPrototypeOf():为参数对象设置原型,返回该参数对象 Object.getOwnPropertyNames():返回一个数组,成员是参数对象本身的所有属性的键名,不包含继承的属性键名 Object.create():接受一个对象作为参数,然后以它为原型,返回一个实例对象
2.实例方法
Object.prototype.isPrototypeOf():判断该对象是否为参数对象的原型
Object.prototype.__proto__:实例对象的__proto__属性(前后各两个下划线),返回该对象的原型。该属性可读写
Object.prototype.hasOwnProperty() :返回一个布尔值,用于判断某个属性定义在对象自身,还是定义在原型链上
3、对象的拷贝
第一种方式:
function copyObject(orig) {
var copy = Object.create(Object.getPrototypeOf(orig));
copyOwnPropertiesFrom(copy, orig);
return copy;
}
function copyOwnPropertiesFrom(target, source) {
Object
.getOwnPropertyNames(source)
.forEach(function (propKey) {
var desc = Object.getOwnPropertyDescriptor(source, propKey);
Object.defineProperty(target, propKey, desc);
});
return target;
}
第二种方式(利用ES2017的Object.getOwnPropertyDescriptors方法):
function copyObject(orig) {
return Object.create(
Object.getPrototypeOf(orig),
Object.getOwnPropertyDescriptors(orig)
);
}
6、严格模式
-
设计目的
明确禁止一些不合理、不严谨的语法,减少 JavaScript 语言的一些怪异行为。 增加更多报错的场合,消除代码运行的一些不安全之处,保证代码运行的安全。 提高编译器效率,增加运行速度。 为未来新版本的 JavaScript 语法做好铺垫。
-
启用严格模式
严格模式可以用于整个脚本,也可以只用于单个函数。 启用方式是在脚本或者函数的第一行:`'use strict';`
-
显式报错(使得 JavaScript 的语法变得更严格)
严格模式下,设置length属性以及不可配置的属性都会显式报错 严格模式下,对一个只有取值器(getter)、没有存值器(setter)的属性赋值,会报错。 严格模式下,对禁止扩展的对象添加新属性,会报错 严格模式下,使用eval或者arguments作为标识名,将会报错。 严格模式下,函数有多个重名的参数,这属于语法错误 正常模式下,禁止八进制的前缀0表示法
-
增强的安全保护
全局变量必须显式声明 禁止 this 关键字指向全局对象(避免无意间创造全局变量) 禁止使用 fn.callee、fn.caller、fn.arguments 禁止使用 arguments.callee、arguments.caller 禁止使用delete删除变量(只能删除对象的属性,且属性的描述对象的configurable属性设置为true)
-
静态绑定(属性和方法到底归属哪个对象,必须在编译阶段就确定)
禁止使用 with 语句 创设 eval 作用域 arguments 不再追踪参数的变化
-
准备过渡ES6
非函数代码块不得声明函数(不允许在非函数的代码块内声明函数) 新增了一些保留字(implements、interface、let、package、private、protected、public、static、yield等)
7、异步操作
1、概述
-
JavaScript是单线程异步执行的(事实上,JavaScript 引擎有多个线程),为了简单,避免锁机制等
-
JS引擎根据异步任务的类型,提供多个任务队列(task queue),只有同步任务执行完毕了才会执行异步任务,异步任务执行完毕则程序执行结束
-
只要同步任务执行完了,引擎就会去检查那些挂起来的异步任务,是不是可以进入主线程了。这种循环检查的机制,就叫做事件循环(Event Loop)
-
异步操作的模式
基本方式:回调函数 事件监听(事件驱动模式,可以绑定多个事件以及去耦合,缺点是不利于阅读) 发布/订阅(“观察者模式”,与事件监听类似,但是可以查看信号和 订阅者,监控程序运行)
-
异步操作的流程控制
回调噩梦 串行执行(编写一个流程控制函数) 并行执行(也是一个流程控制函数) 并行串行结合(使用一个变量控制最多并行执行的任务个数)
2、定时器
-
定时器函数:
setTimeout():用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器
setInterval():用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行
clearTimeout():取消setTimeout()设置的定时器
clearInterval():取消setInterval()设置的定时器 -
debounce函数(防抖动,多出现在用户连续点击提交这类情况下)
$('textarea').on('keydown', debounce(ajaxAction, 2500)); function debounce(fn, delay){ var timer = null; // 声明计时器 return function() { var context = this; var args = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.apply(context, args); }, delay); }; }
-
setTimeout和setInterval指定的回调函数,必须等到本轮事件循环的所有同步任务都执行完,才会开始执行。由于前面的任务到底需要多少时间执行完,是不确定的,所以没有办法保证setTimeout和setInterval指定的任务,一定会按照预定时间执行。
-
setTimeout(f, 0):等所有同步执行完毕,然后执行f(不一定0毫秒后执行,看情况)
将DOM操作(JS执行速度远高于DOM)放到最后,防止浏览器“堵塞” var div = document.getElementsByTagName('div')[0]; // 写法一 for (var i = 0xA00000; i < 0xFFFFFF; i++) { div.style.backgroundColor = '#' + i.toString(16); } // 写法二 var timer; var i=0x100000; function func() { timer = setTimeout(func, 0); div.style.backgroundColor = '#' + i.toString(16); if (i++ == 0xFFFFFF) clearTimeout(timer); } timer = setTimeout(func, 0);