最近在复听沙老师的陪你读书系列教程,遂决定将之前琐碎的笔记整理成文。
script 标签
script标签是向HTML插入JavaScript的主要方法。
标签的属性
async异步下载(只对外部脚本有效,一般不用)charset字符集(大多数浏览器会忽略这个值,一般不用)defer延迟执行(只对外部脚本有效,IE7及更早版本对嵌入脚本也支持这个属性,一般不用)language语言(已废弃)src包含代码的外部文件typeMIME—— 多用途互联网邮件拓展,language的代替属性(一般不用)
标签的位置
一般情况下JavaScript代码放在body的结束标签之前,因为其是阻断式。一定要在渲染之前执行时放会放在头部,如以下两种情况:
Rem设置根字体的大小- 检测
CSS属性兼容性
嵌入代码与外部文件
外部文件优点:
- 可维护性
- 可缓存(避免缓存方式:浏览器设置,请求文件后加随机数)
- 适用未来
嵌入代码优点:
- 减少连接数,提升性能
注意
- 包含在标签内部的
JavaScript代码将被从上至下依次解释解释包含
预处理和执行两个过程。 src属性可以跨域- 带有
src属性的标签只会下载并执行外部脚本文件,不会执行标签之间嵌入的代码
语法
JavaScript严格区分大小写,但在HTML和CSS中使用时是不区分大小写的。
- 在
HTML中绑定事件时,事件名不区分大小写,但等号后面的属性值是区分大小写的 data-属性 “-” 后面会被强制转换成小写- 在
JavaScript代码中onclick等事件名称必须全部是小写
标识符和注释
标识符指的是变量、函数、属性的名字,或函数的参数。
标识符的第一个字符必须是字母(包含任何语言,如汉字等)、下划线或$。
//单行注释
/*
块级注释
*/
语句
JavaScript解释器处理未在结尾处加分号的代码时,会先判断下一行的代码能否跟当前行一起执行,如果能执行就合并两行代码。如果不能执行就在行尾和下一行之间加分号执行,如果加分号还是不能执行就报错。
// 不会和下面代码合并
return
break
continue
//会和下面一行结合
++ / --
var a = 1
var b = 2
a
++
b //a:1 b:3
数据类型
JavaScript包含Number,String,Boolean,undefined,null,Object共 (5 + 1) 种数据类型。
typeof操作符的返回值都是字符串:
"undefined","boolean","string","number","object","function"。
var a = true
var b = true
alert(typeof a == b) //false
undefined 和 null 异同
- 都只有一个值
- 参与判断都返回
false - 都没有方法
null是关键字,undefined不是null是特殊的对象,undefined本质是windows对象的一个属性,属性的值是未定义null是已经初始化的,undefined是未初始化的null返回值是 "object",undefined是 "undefined"- 转换成数字时
null返回 0,undefined返回NaN
用法
- 当声明一个不确定是什么类型的变量时用
null - 当用全等检测一个值是否为空时用
null - 当用全等检测一个值是否存在时用
undedined
Boolean
只有undefined,null,-0,0,NaN,""转换为布尔类型时值为false,其余都为true。
Boolean(new Boolean(false)) // true
Boolean()等同于做两次非运算。
Boolean(param) == !!param // true
Number 和 String
-
尽量使用十进制,尽量少用十六进制,尽量不用八进制 (严格模式下无效)
-
整数范围
-253 ~ 253,开发中尽量不要超过十六位,超过会转换成科学计数法表示 -
JavaScript和CSS中小数点前可以不写数字,默认为零;小数点后面没有数字会自动转换成整数;小数点后面连续的零超过六位会转换成科学计数法表示.5 => 0.5 1. 1.00 1.0 => 1 0.0000001 => 1e-7 -
0/0返回
NaN, 正数/0返回Infinity, 负数/0返回-InfinityNaN != NaN // ture isNaN() // 判断传入的值是否能转换成数字。
数值转换
Number可以把任何数据类型转换为数字,结果一定为数字。parseInt和parseFloat用于转换字符串。
Object
与原始类型不同点:
- 对象有属性
- 对象有方法(特殊属性)
var a = 'abcd' a.len = 4 alert(a.len) // undefined a.toUpperCase() alert(a) // abcd - 对象是可以改变的,原始数据类型不能改变
分类
- 内部对象(17个)
- 错误对象
- 常用对象
Number,String,Boolean,Array,Fuction,Object,Date,RegExp - 内置对象
Math,JSON,global
- 宿主对象(平台决定)
Window,Document - 自定义对象
对象创建
- 对象字面量
new操作符Object.create(ES5)Object.create(param1, param2) //param1:要继承的原型,param2:对象的描述信息
对象属性的查询
- 对象属性查询操作符
.操作符[]操作符
解释器遇见属性查询操作符查询对象属性时,先判断操作符前面是否是
null或undefined,如果是直接报错。然后继续判断是否是对象类型,如果不是转换成对象。此时操作符如果是.直接返回属性名所对应的值。如果是括号,那么先计算括号中的值并将结果转换成字符串,然后返回该属性名所对应的值。如果属性或者属性值不存在返undefined。
对象转换
原始类型 to 对象:
- 数字
let a = 123 Object(a) // {[[PrimitiveValue]]: 123} - 字符串
let a = '123' Object(a) // {[[PrimitiveValue]]: '123', 0: "1", 1: "2", 2: "3", length: 3, [[PrimitiveValue]]: "123"} ``` - 布尔
let a = true Object(a) // {[[PrimitiveValue]]: true} null和undefined转换成对象都返回{}
对象 to 原始数据类型:
对象转换为布尔,结果一定为
true。对象转成数字先调用
valueOf,得不到数字再调用toString。对象转成字符串先调用
toString,得不到字符串再调用valueOf。对象转成原始值先调用
valueOf,得不到原始值再调用toString。
toString返回带双引号的值valueOf有原始值返回原始值,没有返回对象本身[1,2,3].toString() => "1,2,3" //toString在处理数组时的特殊情况 (new Date()).valueOf() => 距离1970.1.1的毫秒数 //valueOf在处理时间对象时的特殊情况
注意
一个数据转换成二进制,如果前三位都是零,那么
typeof的返回值为Object。
表达式
- 原始表达式
- 常量
- 变量
使用
var操作符定义是局部变量,反之是全局变量使用
var操作符定义不可以被删除,反之可以删除使用
var操作符定义变量,会发生声明提升,反之不会 - 直接量
- 关键字
- 初始化表达式
- 函数定义表达式
- 函数调用表达式
- 属性访问表达式
- 对象创建表达式
操作符
优先级: 属性访问>一元操作符>乘除>加减>比较>相等>与运算>或运算>三目运算>赋值运算>逗号运算
结合性: 所有的一元操作符,三目运算符,赋值运算符,都是右结合,其余都是左结合。
一元操作符
+任何数据类型进行一元加操作返回结果都是数字类型-任何数据类型进行一元减操相当于先进行一元加操作再取负数++--~按位非~10 => -10 -1 // 如果对数字进行位非运算,结果是其取负数在减去1!逻辑非typeofvoiddelete返回一个布尔值
逻辑运算符
-
与运算
- 两个布尔值运算时,有一个为
false,返回false。两个都为true,返回true - 如果并且 (a==1 && b==3)
- 如果那么,短路写法(a==1 && b=3)
- 两个布尔值运算时,有一个为
-
或运算
- 两个布尔值运算时,有一个为
true,返回true。两个都为false,返回false - 或者(a==1 || b==3)
- 如果不,那么,一般用于赋值(x = a || b)
- 两个布尔值运算时,有一个为
加减乘除和比较赋值
-
加法操作符
如果两边都是
数字、布尔、null或undefined类型就进行数字的相加。如果两边有一个是
字符串就进行字符串的相加。 -
减法操作符/乘性操作符(乘法\除法\模运算)
如果操作符两边都是
数字,那么直接进行计算;如果有非数字类型,先把操作数转换成数字,然后进行运算。操作数有
小数字类型数的时候,需要做一些处理(IEEE754浮点数问题)。结果一定是
数字类型。 -
关系运算符
如果有一个是
数字,另一个就转换成数字。如果有一个数
NaN,返回false。结果一定是
布尔类型。7 > 6 > 5 //false -
相等运算符
- === / !== (首先判断类型)
数字:比较数值是否相等 NaN != NaN。
布尔:比较布尔值是否相等。
字符串:比较字符串编码是否相同。
对象:比较对象的引用。
- == / != (会进行隐式类型转换)
数字、字符串、布尔混合运算时,先转换成数字,再进行比较。
null == undefined 结果是 true。
如果操作数存在对象,那么把对象转换成原始值再进行比较。
以上三种情况都不符合直接返回false。
-
赋值运算符(左侧的值叫左值,一定是一个变量或属性。尽量不要在代码中写连续赋值)
语句
语句:会促使某件事情发生的命令叫语句,一定伴有副作用。
副作用:运行语句或执行表达式对某些变量的值进行修改,删除,增加操作(++ , -- , =)。
基础语句
- 表达式语句,表达式带有副作用(++ ,-- , = , +=,-=,*=, /= ,%=,delete,函数调用)
- 复合语句(代码块)
- 空语句(解释器略过不进行任何操作,常用在代码块的开头解决压缩代码导致的异常)
- 声明语句
var、function
分支语句
- 分支语句
if,switchif语句中判断条件如果是值的比较,那么用全等判断。
switch语句中的case是全等判断。
switch语句中的default可以写在任意位置,始终最后执行。
switch语句中的case会从上到下依次执行,不会因为某一条件符合就中断执行,所以一般在case中加break。
循环语句
- 循环语句
while,do while,for,for in - for
- 循环判断表达式直接返回布尔类型会减少一次隐式类型转换
- 循环表达式右侧为数组长度时,建议先定义数组长度为一个变量
- for-in
该循环主要用来枚举对象的属性。先对in操作符后面进行对象类型的转换,如果是null或undefined就报错(ES5不报错,变更为不执行循环体),如果是其他的原始类型转换成包装对象。然后把对象属性取出来运行in操作符前面的表达式,并将属性赋值给表达式的结果。
in前面的表达式可以是任意的,但结果一定是一个左值(变量,对象的属性)in前面的表达式每次循环后都会被执行一次in后面的表达式如果是原始类型时,数字类型和布尔类型不执行任何操作,字符串返回0 ~ array.length-1- 不是所有的属性都可以被枚举,如:
length,toString,valueOf,PrimitiveValue等 - 如果一个对象继承了某个对象,继承的属性和方法也会被枚举出来
- 如果对没有被枚举的属性进行删除,或者动态增加对象的属性,那么这些属性不会被枚举出来
- 大部分浏览器是按照属性的定义的顺序枚举(先定义先枚举);如果属性是整数类型的(0,1,2...),那么就按照数字的顺序枚举
- 不建议在
for-in>循环中进行数组的操作
中断语句
continue停止当前的某一次循环或者switch分支,可以与标签语句配合使用break退出当前的循环或者switch语句,可以与标签语句配合使用return结束所在函数并返回操作符后在同一行的表达式throw停止运行JavaScript,依次查找异常处理程序
作用域和内存
- 声明的
函数和变量如果是同名,那么在当前作用域下函数会覆盖变量 作用域可以嵌套,但是不可以重叠eval,with可以改变作用域(破坏了解释器创建和管理作用域的规则,有性能问题)
var a = '123'
a = null // 下一次垃圾回收机制循环会对变量a进行回收。
编译过程:创建一个全局作用域 => 词法语法分析 (如果发现声明语句,如果作用域有该变量/函数则忽略,如果没有则创建变量/函数并分配一定内存空间,创建该函数的作用域) => 生成一段可运行代码。 执行过程:可运行代码在执行时会生成作用域链。
数组的使用
数组中每一项都可以保存任意类型的数据。
数组长度可以随时调整。
创建
new操作符/** * 只有一个数字类型参数时指的是数组的长度 * 其他情况参数即是数组的内容 */ new Array(1) => [empty] new Array(1, 2) => [1, 2]对象字面量
最后一项后面不能有逗号,ie7不兼容。
不要使用多个逗号创建空数组,不同浏览器解析方式不一样。
检测
- instanceof
//多个iframe或多个全局环境时可能会出错 var arr = [] arr instanceof Array //返回true - constructor
//多个iframe或多个全局环境时可能会出错 var arr = [] arr.constructor == Array //返回true - isArray
//ES5 var arr = [] Array.isArray(arr) //返回true - Object.prototype.toString.call
var arr = [] Object.prototype.toString.call(arr) == '[object Array]'
方法
- 栈方法
push //返回操作后数组的长度 pop //返回本次弹出的项 - 队列方法
unshift //返回操作后数组的长度 shift //返回本次弹出的项 - 排序方法
reverse //反转 /** * 不传参数时先把数组的每一项转换成字符串,然后按照字符串的ASCALL码进行排序 * 接收函数排序 sort(function(a, b) { return a - b }) */ sort - 操作方法
/** * 原有数组不变 * 默认是逗号 */ join /** * 原有数组不变 * 一维数组会被拆分添加,二维数组里面的数组不会被拆分 */ concat /** * 原有数组不变 * 返回截取后新数组(包含开始位置不包含结束位置) * 如果是负数那么就加上数组长度 */ slice splice //操作后得到的数组 - 位置方法(ES5)
/** * 返回都是数字 * 匹配条件是全等 */ indexOf //从前往后找 lastIndexOf //从后往前找 - 迭代方法(ES5)
/** * 参数:function(item, index, arr) {} * item 当前项 * index 当前项索引 * arr 数组本身 */ every some filter map forEach - 归并方法(ES5)
/** * 参数:{param1:function(pre, current, index, arr) {}, parma2:initValue} * pre 前一项 * current 当前项 * index 当前项索引 * arr 数组本身 */ reduce reduceRight
数组的去重
- 与老数组进行对比(ES3)
- 与老数组后面的项对比(ES3)
- 去掉重复的(ES3)
- 对象属性名不重复方法(ES3)
- 先进行排序再去重(ES3)
indexOf(ES5)Setlet arr = [] //方式1 Array.from(new Set(arr)) //方式2 [...new Set(arr)]
注意
使用
delete删除数组的某一项不会导致数组长度的变化,但是删除的那项的值会变成undefined。
length属性总是返回正整数或者零,最大长度232 -2。
时间对象
GMT格林威治(本身有一定误差,包含时区)。
UTC世界协调时间。
创建
new Date() //返回系统当前时间
new Date(1) //返回距离1970年1毫秒的时间
new Date(2018,10,10) //返回2018年11月10号
//返回1970年1月1号8点
new Date(null)
new Date(true)
new Date(false)
new Date(undefined) //返回不合法时间 Invalid Date
//参数为字符串时建议格式:月/日/年 时:分:秒
new Date("2014-04-15") // Tue Apr 15 2014 08:00:00 GMT+0800 (中国标准时间) 包含时区信息
new Date("2014/04/15") // Tue Apr 15 2014 00:00:00 GMT+0800 (中国标准时间)
方法
- 继承方法
toString //包括时区信息,不同宿主环境结果可能不一样 toLocalString // 不包含时区信息,不同宿主环境结果可能不一样 valueOf //时间对象的毫秒数 now //时间对象的毫秒数,ES5 - 格式化方法
//很少应用 toTimeString toDateString toLocalTimeString toLocalDateString toUTCString //相对于UTC格式,不同宿主返回字符可能不一样,一般用于设置cookie的过期时间 toGMTStirng //相对于GMT格式,一般不用 - 自身方法(33个)
/** * 28个有规律的 * 年月日时分秒毫秒 * set * get * UTC * no UTC * */ //特殊的5个 getTime setTime getDay getUTCDay getTimezoneOffset
注意
getYear已废弃- 时间对象中只有天是从1开始的,月份、星期、时分秒、毫秒都是从0开始的
get返回值都是数字,set返回值都是时间对象set方法设置数值大于最大数值时,会自动进位前面的日期(年份、月份、星期、时分秒)// 时间对象转换成毫秒数速度 valueOf == getTime > Number == +(一元加) > Date.parse
函数的创建
-
函数声明语句
function funcName (param: 形参) { 函数体 } //函数体内外部都能访问函数 -
函数表达式语句(匿名函数表达式语句)
/** * 赋值变量 * 对象属性值 * 回调函数 */ var funcName = function (param: 形参) { 函数体 }函数声明语句,函数会被整体提升。函数表达式语句只会提升定义的变量,函数体不会被提升。
语句块中不要使用函数声明语句(严格模式下报错,普通模式下也会因为宿主环境的不同有不同的解析)。
-
命名函数表达式语句
/** * 函数体内部能访问函数(递归应用;调试应用) * ie8 bug: 赋值操作符右边的函数会像函数声明语句一样被解析,发生函数声明提升, * 导致函数体外面也能访问函数,造成当前作用域下的命名污染。 * hack: 将变量名和函数名起成相同的。 * */ var varName = function funcName (param: 形参) { 函数体 } -
箭头函数
/** * 不会创建自己的上下文环境 * 匿名函数没有arguements对象 * */ (param: 形参) => {} -
函数生成器
function * funcName (param: 形参) {} -
函数构造器(传参复杂需转换成字符串;解析时需调用一次eval函数;不能访问当前作用域)。
JS中的作用域
IIFE方式
(function(){})();
(function(){}());
var a = function () {} ();
//webpack打包后代码
true && function(){}();
false || function(){}();
0,function(){}();
/**
* 早期bootstrap源码
* 一元加,一元减,位操作性能偏低,非操作性能稍微好一点
* */
+function(){}()
-function(){}()
~function(){}()
!function(){}()
new function () {} //不建议使用,可能会有歧义
作用
- 避免作用域下
命名污染 - 减少作用域的查找,对整个程序性能有提升
- 有利于压缩(名字较长的全局变量
document,windows,jquery可以在函数内简化D,W,$) - 保存
闭包的状态(for循环中执行异步操作时,用IIFE包裹,将当前索引当做实参传进去) - 颠倒代码的运行顺序
// UMD通用模块规范 (function(funcName){funcName()})(function(){})
注意
括号方式的IIFE建议在前面加上分号。
with和try catch中的catch会创建块级作用域。
函数的应用
- 函数当成值(函数表达式、对象属性值、数组对象的项)
- 函数作为另一个函数参数
- 操作函数,无时间差
sort等 - 回调函数,有时间差
AJAX,Nodejs文件读取等异步操作
- 操作函数,无时间差
- 函数作为另一个函数返回值(闭包等)
闭包
函数里面嵌套函数,返回这个函数并被引用,导致垃圾回收机制不会回收该函数占用的内存,在函数作用域外部可以访问内部作用域的现象。
作用域、作用域链、执行环境和活动对象
运行一段代码(全局下):解释器会创建一个全局作用域,全局作用域下包含一个叫作用域链的列表,作用域链上包含一个叫活动对象的对象。
预处理:解释器对代码进行词/语法分析,如果遇见声明语句,先判断当前活动对象里是否包含该属性,如果有则忽略,否则就创建该属性并将其赋值为undefined。该过程结束后会生成一段可执行代码。
执行:对变量进行赋值时,会依次查看作用域链上的活动对象,如果有就进行赋值操作,如果没有就在全局活动对象上创建该属性并赋值。
包装对象
包装对象:数字、布尔和字符串类型调用方法,或进行属性访问时会先转换成对应的对象,然后再进行相应操作。这种调用的同时被创建的对象叫做包装对象。
布尔类型包装对象的方法
valueOftoString
数字类型包装对象的方法
valueOftoStringtoFixed(param:保留小数点位数)//保留位数不要超过20位 //保留小数时是按照四舍五入的规则进行的toExponential(保留小数点位数) => 转换成科学计数法toPrecision(所有数字的位数)
字符串类型包装对象的方法
valueOftoStringcharAt(获取指定位置的字符,从零开始)charCodeAt(获取指定位置的字符编码,从零开始)concat(字符串拼接,很少用)indexOf(获取第一个匹配的字符在字符串中的位置)lastIndexOf(获取最后一个匹配的字符在字符串中的位置)split(对字符串通过特定“标识”进行分割)slice、substr、substring/** * slice,substring * 相同点: * 包含起始位置,不含结束位 * 传一个参数时,从当前参数的位置截取的字符串的最后 * 不同点: * 当第二个参数小于第一个参数,substring会调换,slice不会 * 参数有负数时,substring会将参数转换成零,slice会将参数当做倒数第几位处理 */ slice(param1:'开始位置',param2:'结束位置') substring(param1:'开始位置',param2:'结束位置') /** * 参数有负数时,会将参数转换成零 */ substr(param1:'开始位置',param2:'截取位数')toLowerCase(转换成小写)toUpperCase(转换成大写)trim(去除空格)trimLefttrimRightpadStart(填充)(ES6)padEnd(ES6)startsWith(ES6)endsWith(ES6)includes(是否包含某段字符)(ES6)repeat(重复几次当前字符串)(ES6)search(正则)match(正则)replace(正则)
单体内置对象
不依赖于宿主环境,并且在JavaScript执行前就存在的对象。
不可以使用new操作符实例化。
ECMA规范的三个原则:
- 所有浏览器相关代码都删除
- 对象与平台无关
- 全面支持
Unicode编码
global 对象
//属性
undefined
NaN
Infinity
//处理数字方法
isFinite
isNaN
parseFloat
parseInt
//处理URI方法
encodeURI //把整个URI字符进行编码
encodeURIComponent //对部分URI字符进行编码
decodeURI
decodeURIComponent
escape //只能处理ASCALL码进行处理
unescape
/**
*低版本浏览器下将字符串转换成JSON
*动态声明一些变量
*一些代码压缩
*/
eval
注意
eval函数声明的变量不会发生声明提升- 严格模式下,
eval函数定义的变量,在eval外部是访问不到的 eval中使用的代码,无法使用调试工具调试eval函数破坏了JavaScript解释器作用域规则,性能会大幅度下降eval存在安全隐患,执行用户输入时要做验证
Math 对象
//属性
PI(π)
round //对现在的数字加0.5后向下取整
ceil //比当前值大的最小的整数
floor //比当前值小的最大的整数
/**
* ES3下只能接受两个
* ES5可以接受多个参数
*/
max
min
abs //绝对值
random //生成 0~1 之间的随机数
对象设计模式
- 工厂模式
解决:创建多个相似对象。
问题:无法识别对象类型,
constructor的值是Object。 - 构造函数模式
解决:可以识别对象类型,
constructor的值是构造函数。 问题:构造函数的所有方法和属性都会在创建的对象上实例化一遍。new操作符:创建一个对象 => 将构造函数的作用域赋值给新的对象 => 执行函数中代码 => 返回创建对象
工厂模式和构造模式异同:1.没有显式的创建对象 2.将所有的属性和方法赋值给this 3.没有显式的return语句
- 原型模式 解决:占用内存问题。 问题:所有的实例都共用共同的属性和方法。
- 组合模式(构造函数加原型模式)
方法
- isPrototypeOf(检测对象是否是某个实例的原型)
var object = {} object.prototype.isPrototypeOf(object) - hasOwnProperty(检测对象自身是否包含某个属性)
var object = {} object.hasOwnProperty('property') - propertyIsEnumerable(检测对象某个属性是否可枚举)
var object = {} object.propertyIsEnumerable('property') - getPrototypeOf(ES5,返回对象的原型)
var object = {} Object.getPrototypeOf(object) - for in循(获取所有可枚举属性)
var object = {} for(let i in object) {} - keys(获取对象所有可枚举的自有属性)
var object = {} Object.keys(object)
注意
constructor在ES3下可枚举,在ES5下不可枚举ie8下对象的属性名如果和Object上不可枚举方法同名会造该属性不可枚举
JavaScript中的继承
- 原型链继承 优点:1.使用简单;2.在父类的原型中可以动态增加属性和方法。 缺点:1.为子类增加方法时,在放在继承之后;2.无法实现多继承;3.所有属性共享;4.无法传递参数
- 借用构造函数继承 优点:1.可以多继承;2.解决属性共享问题;3.可以传递参数。 缺点:1.只是子类的实例,没有继承父类;2.只能继承构造函数内的属性;3.属性无法复用,浪费内存。
- 组合式继承(伪经典模式) 缺点:1.父类的构造函数被调用两次,影响性能;2.相同属性同时存在在构造函数和原型中占内存。
- 原形式继承
- 寄生式继承
- 组合寄生式继承(经典继承)
window对象
每一个框架都会包含自己的window对象,都保存在frames集合中,可以通过索引或名称的方式访问。
如果一个页面存在多个window对象,那么每一个window对象都会包含原生的构造函数,且它们之间是相互独立、互不相等的。
window对象的属性
- top(最外层的
window对象) - parent(当前
window对象的上一层) - self(当前的
window对象) - open方法
/** * parma1: 要加载的url * parma2: 窗口目标,可以取值frame的name, _top, _self, _parent, _blank(默认值) * parma3: 特性字符串=>每一项使用逗号分隔,且不能包含空格;如果没有新开窗口,则此参数失效。 * parma3: 布尔类型,是否取代浏览器历史记录。 */ open(parma1, parma2, parma3, parma4)
间歇与超时
- setTimeout
- setInterval
/** setTimeout, setTimeout * parma1: 回调函数 | 字符串(相当于调用了一次eval函数) * parma2: 数字 */ var timerId1 = setTimeout(param1, parma2) var timerId2 = setInterval(param1, parma2) - clearTimeout(timerId1)
- clearInterval(timerId2)
注意
- 定时器是异步的
- 使用setInterval时,H5规定的最小时间间隔是10ms,实际上在60Hz的显示器下最小时间间隔是16.7ms
- setInterval函数具有累积效应,使用setTimeout来代替它
- 做动画效果时,使用requestAnimationFrame代替定时器会更流畅
系统对话框
- alert(string) 无返回值
- confirm(string) 确认按钮返回true, 取消按钮返回false
- prompt(string,输入框默认值) 返回用户在输入框内输入的值
注意
- 三个对话框操作都是阻断式的
- 对话框的样式是浏览器配置的
location对象
location对象既是window对象的属性,也是document对象的属性。
location的属性
- hash
- host
- hostname
- href
- pathname
- port
- protocol
- search
location的方法
- replace 不会生成新的浏览记录
- reload(params:Boolean) 是否绕过缓存
注意
- location对象的属性都是可写的,对除了hash属性之外的属性赋值,会导致页面刷新,且会生成一条新的浏览记录
history对象
history的属性
- go(params: 整数 | url) 前进/后退几页、
- back
- forward
- length 历史浏览记录的数量
Node节点
Node属性
- nodeType 返回 1~12 代表不同类型的节点
- nodeName 返回一个当前节点名称的字符串
- nodeValue 返回null或当前节点的值
- childNodes 返回nodeList对象
- parentNode 返回父节点
- previousSibling 返回前一个兄弟节点
- nextSibling 返回后一个兄弟节点
- firstChild 返回第一个子节点
- lastChild 返回最后一个子节点
- ownerDocument 当前文档的文档节点
Node方法
- hasChildNodes 返回布尔类型 => true:有子节点,false:没有子节点
- appendChild(param: node类型节点)
- insertBefore(param1: 要插入的节点,param2: 参照节点)
- removeChild(param: 要删除子节点)
- replaceChild(param1: 要插入的节点,param2: 要替换掉的节点)
- cloneNode(parma: Boolean) 参数为ture,进行深度克隆;参数为false,克隆当前节点
- normalize 合并文本节点
documnet节点
属性
- documentElement 对应HTML节点
- body 对应HTML中的body节点
- title 对应网页的标题
- domain 对应网页域名信息,只能从低级域名改成高级域名
- referrer 获取前一个页面地址
element节点
属性
- nodeType的值是1
- nodeName的值是标签名字(大写的)
- nodeValue的值是null
- id 可以获取元素节点的id值
- title 可以获取元素的title值
- dir 取值 ltr | rtl
- className
方法
- getElementById
- getElementsByName
- getElementsByTagName
- getElementsByClassName
- querySelectorAll
- querySelector
- createElement
特性
HTML标签特有的属性,称为该标签的特性。可以用**node['attribute']**获取或设置。
非标准特性/用户自定义特性
- getAttribute
- setAttribute
- hasAttribute
- removeAttribute
使用这些方法读取/设置标准或者非标准特性,都是字符串形式。 JavaScript中的关键字,在这些方法中是可以正常使用的。
数据集属性 data-*
在JavaScript中使用dataset['attribute']形式获取属性。
连字符形式的属性用驼峰形式获取属性。
dataset属性是实时双向接口。
注意
- 无论在HTML中属性书写的方式是大写或小写,在
JavaScript中都使用小写。如果是多个单词组成的属性,那么使用驼峰规则。 HTML中一些属性在JavaScript中是关键字,使用时需要进行特殊转换。JavaScript中获取的属性值可能是字符串、布尔、数字、function或样式对象。- 属性被设置后是无法删除的。
text节点
属性
- nodeType的值是3
- nodeName的值#text
- nodeValue的值是文本本身
方法
- appendData(param:文本)
- deleteData(param1:位置, param2:数量)
- insertData(param1:位置, param2:文本)
- replaceData(param1:位置, param2:数量, param3:文本)
- splitText(param:位置)
- substringData(param:位置, param2:数量)
- createTextNode(param:文本)
动态加载JavaScript脚本
- 当使用某个脚本时,不确定会在当前页面执行
- 不确定用户加载的是哪个脚本
动态插入的方式
- 创建
script标签,对src属性进行赋值,最后将标签插入文档中 - 创建
script标签,将JavaScript作为文本节点插入标签中,最后将标签插入文档中(ie 不支持将文本节点插入script中) - 创建
script标签,将JavaScript作为文本赋值给text属性,最后将标签插入文档中(Safari 不支持)
加载与阻塞
如果是JavaScript脚本是直接写在HTML页面中时,脚本的加载和运行都是阻塞的。如果是动态加载的JavaScript脚本,下载脚本时不会阻塞,执行脚本会阻塞。
动态加载CSS样式表
- 网页换肤
动态加载的方式
- 创建
link标签,设置标签的type和rel属性,再对标签的href属性进行赋值,最后将标签插入到head标签中 - 创建
link标签,将CSS作为文本节点插入标签中,最后将标签插入到head标签中(ie 不支持将文本节点插入style中) - 创建
link标签,将CSS作为文本赋值给text属性,最后将标签插入到head标签中(Safari 不支持)
注意
- 对于加载
CSS而言,如果想保持各个浏览器展示的一致性,要将创建出的标签插入head中 - 加载远程
CSS需要创建link标签,加载本地CSS需要创建style标签 - 插入页面的
CSS不可以删除,会影响页面样式 - 浏览器渲染
CSS是实时执行的,如果修改了link标签的href属性会直接反应在页面上
动态和静态合集
NodeList是所有类型节点的合集。HTMLCollection是只包含元素节点的合集。 NodeList、HTMLCollection和NamedNodeMap都是动态合集。querySelector和querySelectorAll获取的NodeList是静态合集。
注意
NodeList和HTMLCollection都是伪数组,ie中不能使用slice方式转换成数组NodeList和HTMLCollection都有item方法- 使用
childNodes获取的是NodeList,使用children获取的是HTMLCollection
class和焦点管理
- 自定义
getElementsByClassName(H5)方法,因为需要遍历所有节点,所以性能差。且返回的是数组,不是HTMLCollection - 调用
classList(H5)属性会获得一个DOMTokenList对象,该对象包含add,remove,contains,toggle四个方法 activeElemen在文档加载期间的值是null,加载完成后会指向body,操作时指向被操作目标
判断文档是否获取焦点,使用document.hasFocus方法,可以判断用户当前是否在和网页进行交互。
文档元素获取焦点方式:
- 文档默认加载
- 用户操作(键盘、鼠标、触摸事件等)
- 使用
focus方法
焦点管理的意义
- 标准的焦点管理,可以让
HTML开发标准化 - 无障碍
Web应用 - 提升用户体验
使用字符串操作DOM节点
- innerHTML
- outerHTML
- 读模式下,不同浏览器返回结果不同(标签大小写,空格,缩进等)
- 写模式下,设置的值和解析的
dom结构可能会不一样(特殊字符转换,浏览器纠正等) - 插入
script标签时,标签内JavaScript代码不会执行;插入style标签时,样式会生效(ie8 之前不支持script,style标签开头的字符串) 4.table标签不支持这两种属性
- innerText
- outerText
- 写模式下,赋值的字符串会被转换,但展示结果与赋的值一样
innerText和outerText不是H5规范的标准outerText基本用不到- 部分浏览器不兼容
innerText,需要用textContent替代(火狐等)
innerText和textContent
区别:
textContent返回的值包含script和style标签内容,innerText不包含innerText返回值依赖于页面的显示,textContent依赖的是代码内容innerText赋值时会触发回流操作,textContent不一定会innerText赋值时值会被格式化,textContent不会- 文本节点
nodeValue,返回结果类似textContent
自闭和元素的处理
br,hr等标签设置innerHTML和innerText时,浏览器会将自闭和标签变成闭合标签,但是插入的内容不会显示在页面上。设置表单标签时可能会影响表单元素的value值,不同浏览器效果不同。
JavaScript中的滚动操作
元素滚动
scrollIntoView,scrollIntoViewIfNeeded,scrollByLines,scrollByPages方法都是针对目标元素的。
/**
* H5 规范
* 兼容 ie8 以上浏览器
* param: true => 被调用元素的顶部将和滚动区域的顶部对齐 false => 被调用元素的底部将和滚动区域的底部对齐
* 火狐浏览器可以传递一个{ behavior: 'auto|instan|smooth', block: 'start|end' } 对象作为参数
*/
scrollIntoView(param: Boolean | Object)
注意
scrollIntoView是基于dom节点在文档流的存在方式实现的,display属性为none的节点调用该方法没有效果scrollIntoView方法对横向和纵向滚动都生效- 本身在视窗中且不再顶部或底部的元素调用
scrollIntoView方法,浏览器依然会发生滚动 - 本身在视窗中的元素调用
scrollIntoViewIfNeeded方法,浏览器不会发生滚动
页面滚动
定点滚动:向某一个位置或某一个方向滚动。scrollTo,scrollBy方法是window对象的方法。
/**
* *param1: 滚动到页面横轴方向的X处
* *param2: 滚动到页面纵轴方向的Y处
*/
scrollTo(param1: Number, param2: Number)
/**
* *param1: true => 像横轴正或反方向滚动 X px
* *param2: true => 像纵轴正或反方向滚动 Y px
*/
scrollBy(param1: Number, param2: Number)
滚动属性
scrollTop属性可以获取或设置元素的内容的垂直滚动像素,基于节点在文档流的存在方式实现的。
scrollLeft属性可以获取或设置元素的内容的水平滚动像素,基于节点在文档流的存在方式实现的。
//获取浏览器滚动条距离兼容写法
var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop
var scrollLeft = document.documentElement.scrollLeft || window.pageYOffset || document.body.scrollLeft
scrollHeigth、scrollWidth是只读属性。
- 返回的高度或宽度不包括滚动条的宽度
- 返回的高度或宽度包含
padding,不包含margin - 修改盒模型的
box-sizing属性会对取值有影响 - 不同浏览器取值会有差异,一般参与运算要有容错区间
脚本化CSS
在HTML使用样式表的方式有外部样式表、嵌入式样式表和内联样式表三种方式。
内联样式表
通过dom节点的style属性获取的CSSStyleDeclaration样式对象,只包含内联样式表所对应的样式信息。
注意
CSS属性名包含连字符时,需要将属性名改成驼峰命名CSS属性名为JavaScript保留字时,需要在属性前加前缀(float -> cssFloat)- 所有
CSS的属性都是可读可写 - 如果设置的属性不符合规范,浏览器不会报错,只是不执行
- 混合模式下可以不设置度量单位(不建议)
- 如果在
JavaScript中读取一个没有设置过行内的样式,返回一个空字符串 - 不同浏览器下,
JavaScript读取的颜色值格式不同(rgb,hex)
style对象的属性和方法
/**
* ie8 下所有属性名称是大写的
*/
cssText
/**
* 返回内联样式的个数
*/
length
/**
* 返回CSSRule对象
*/
parentRule
/**
* ie8 及以下不支持
* 返回 'important' 或 ''
*/
getPropertyPriority()
/**
* ie8 及以下不支持
* 返回属性值
*/
getPropertyValue()
/**
* ie8 及以下不支持
* 返回指定位置的CSS属性
*/
item()
/**
* ie8 及以下不支持
* 移除指定样式
* 返回被移除样式属性的属性值
*/
removeProperty()
/**
* ie8 及以下不支持
* propertyName: 属性名
* 属性值: 属性值
* priority: 'important'|null
*/
setProperty(propertyName,propertyValue,priority)
/**
* ie8 及以下不支持
* 返回一个CSSRule对象
*/
getPropertyCSSValue()
计算样式
/**
* ie8 及以下不支持
* element: 获取计算样式的 dom 节点
* pseudoElt: 要匹配的伪元素的字符串
* 返回一个 CSSStyleDeclaration 对象,包含的是当前元素计算后的样式
*/
window.getComputedStyle(element, [pseudoElt])
getComputedStyle(element, [pseudoElt])
document.defaultView.getComputedStyle(element, [pseudoElt])
/**
* 返回一个 CSSStyleDeclaration 对象,包含的是当前元素计算后的样式
*/
currentStyle
注意
getComputedStyle是方法,currentStyle是属性getComputedStyle获取的计算样式是只读的getComputedStyle读取复合属性时有兼容问题,要通过精确属性获取getComputedStyle获取计算样式时,浏览器先通过优先级获取样式表中的样式,然后对值进行计算(样式相互影响),最后进行布局计算(百分比,rem等转换成像素单位)getComputedStyle元素没有设置绝对定位的时候,通过计算属性获取top等属性返回auto字符串getComputedStyle计算样式有不确定性(font-family返回的是一个字符串不会明确当前使用的是那种字体)currentStyle获取的属性值可能会包含百分比
内部和外部样式表
获取StyleSheet对象的方式
document.styleSheets返回一个由StyleSheet对象组成的StyleSheetList(伪数组)- 获取
style或者link标签的dom节点,然后获取节点上sheet属性(ie 下是styleSheet)
StyleSheet对象的属性
cssRules包含当前层叠样式表的属性合集disabled控制当前层叠样式表是否生效hrefmedia返回一个mediaListownerNode当前层叠样式表对象所在节点ownerRule当前层叠样式表是否使用import引入titletype
CSSStyleRule对象的属性
cssText> 当前样式规则完整文本selectorText当前样式选择器style返回当前规则的CSSStyleDeclaration(伪数组)parentRule当前规则是否是import导入的parentStyleSheet返回CSSStyleSheet对象type
CSSStyleDeclaration对象
脚本化CSS类
/**
* classList 是一个伪数组(DOMTokenList对象)
* HTML5 包含以下四个方法
*/
add(class1, class2, ...)
remove(class1, class2, ...)
toggle(class, true|false)
contains(class)
replace(previousClass, currentClass)
注意
className属性只能赋值字符串类型属性值,否则会转换成字符串进行赋值- 会替换原有的
className的属性值
事件
事件是发生于dom元素、document对象或者window对象有关的预定义或自定义的时刻。
事件触发的方式
HTML内联属性- 属性事件(dom0级)
- 事件监听回调(dom2级)
事件的使用
HTML事件的使用
在HTML中每个元素支持的每种事件的都可以用对应的HTML标签来指定事件,通常使用on加事件名称绑定,后面跟上需要执行的JavaScript代码。
HTML事件的注意
HTML事件尽量不要使用特殊符号,如果一定要用需要转义HTML事件执行的JavaScript的代码是在全局作用域下执行的HTML事件在创建时,对应的函数内部会封装一个局部变量event,this指向触发事件的dom元素- 可以使用
setAttribute对HTML事件内部代码进行修改
HTML事件的缺陷
- 时间差
- 代码耦合度
- 全局作用域下,不同浏览器的解析规则可能会造成差异
属性事件的使用(dom0)
添加事件: 获取节点,然后绑定事件属性,赋值事件处理函数。对应的函数内部会封装一个局部变量event,this指向触发事件的元素。
删除事件:获取节点,然后绑定事件属性,将处理函数设置为null。
属性事件的缺陷
- 一次只能绑定一个事件处理函数
事件监听回调的使用(dom2)
dom2级事件包含事件捕获,事件目标,事件冒泡三个阶段。规范规定捕获阶段不涉及目标。
/**
* param1:事件名称,不包含on
* param2: 事件处理函数
* param3: 事件执行阶段,可以传入一个Boolean值,或{capture: Boolean, once: Boolean, passive: Boolean}对象
*
* 注意:
* 事件处理函数中的 this 指向 dom元素
* passive 主要是为了解决滚动,触摸等连续触发的耗费性能的事件
* 同一个节点增加多个同一类型的事件监听,有一个没有指定passive,就不会对当前节点优化
* 同一个节点增加多个不同类型的事件监听,后面的会失效
*/
addEventListener(param1, param2, param3)
/**
* param1:事件名称,不包含on
* param2: 事件处理函数
* param3: 事件执行阶段,只需传入一个Boolean值
*
* 注意:
* 一次只能删除冒泡或捕获阶段的一个事件处理程序
* 删除的和添加的函数必须指向同一个引用
*/
removeEventListener(param1, param2, param3)
检查浏览器是否支持passive属性
var isPassive
try {
Object.defineProperty({}, 'passive', {
get: function () {
isPassive = true
window.addEventLister('abc', null, isPassive)
}
})
} catch (e) {
//
}
/**
* 低版本ie下的dom2级事件
* param1:事件名称
* param2: 事件处理函数
*
* 注意:
* 时间处理函数在冒泡阶段执行
* 事件处理函数中的 this 指向 window对象
* 事件处理函数是按照书写相反的顺序执行
* 删除事件时,传入的函数需要与绑定事件的函数必须为同一引用
*/
attachevent(param1, param2)
detachEvent(param1, param2)
事件优先级
事件发生后,事件首先会从window对象向目标元素进行捕获,在捕获的过程中依次触发addEventListener设置为捕获的事件,进入到目标元素及冒泡阶段是按照事件书写的顺序依次执行。
注意
CSS的改变不会改变事件的传播- 移动端的事件穿透
事件对象
常用属性
bubbles返回一个布尔值表示是否是冒泡cancelable返回是否可以取消当前事件的默认行为currentTarget返回当前处理程序正在处理的元素eventPhase返回事件传播的当前阶段(1.捕获 2.目标 3.冒泡)target返回触发此事件的元素type返回当前 Event 对象表示的事件的名称
常用方法
- preventDefault
- stopPropagation
- stopImmediatePropagation
鼠标事件
click单击事件dblclick双击事件contextmenu右键事件mousedown按下鼠标键时触发mouseup释放按下的鼠标键时触发mousemove鼠标移动事件mouseover移入事件mouseout移出事件mouseenter移入事件mouseleave移出事件mousewheel滚轮事件,DOMMouseScroll(火狐)select
鼠标事件对象属性
screenX/screenYclientX/clientYpageX/pageY(ie9以下不支持)layerX/layerY(ie9以下不支持,以border为参考点)offsetX/offsetY(以content为参考点)movementX/movementYctrlKeyshiftKeyaltKeymetaKeybutton-1没按键,0主键,1辅助键,2副键
注意
relatedTarget表示一个与事件相关的次要焦点。存在于focusin,focusout,mouseover,mouseout,mouseenter,mouseleave,dragenter,~~dragexit~~的事件对象中mousewheel事件对象上有一个wheelDelta属性,滚动条向下滚时为负数值,向上滚动时是正数值,值的大小通常是120的倍数。火狐浏览器DOMMouseScroll事件对象上有一个detail属性,滚动条向上滚动是负数值,向下是正数值。HTML5实现了标准的wheel事件对象有上deltaX,deltaY,deltaZ等属性- 鼠标滚动事件与页面滚动无关,只能通过鼠标滚轮、触控板或触控设备的缩放触发
- 鼠标滚动事件的触发与页面是否滚动到顶部和底部无关
参考资料
JavaScript高级程序设计(第三版)