一、写在前面
最近重读《JavaScript 高级程序设计》,总结下来,查漏补缺。
二、JS 简介
2.1 JS 组成
- ECMAscript:以 ECMA-262 为基础的语言,由浏览器支持
- DOM:编程接口(API), 将页面映射成节点结构(文档树),提供操作方法
- BOM:浏览器对象模型,处理浏览器窗口和框架交互(部分扩展)
2.2 <script>
- 实现在 HTML 中插入 JS
- 内嵌,外联(好处:可维护,可缓存,适应未来)
- 推荐放在 body 中、内容后,缩短内容呈现时间(浏览器遇到 body 呈现内容)
参数:
-
async: 立即下载脚本(外部文件),异步执行
- 不保证按出现顺序执行
- 多个 async 时,保证互不依赖,建议无修改 DOM 操作
- 在页面 load 前执行,不一定在 DOMContentLoaded 事件触发前执行
- charset: 指定代码字符集(很少用,部分浏览器忽略该参数)
-
defer: 下载后延迟执行,文档完全解析显示后执行
- 延迟脚本,延迟到 </html> 后执行,页面 load 前执行
- 最好只有一个延迟脚本(HTML5 要求按出现顺序执行,但实际不一定按顺序执行,也不一定会在 DOMContentLoaded 事件触发前执行)
- language: 标明编写语言(废弃)
-
src: 外部文件及地址链接
- src、标签间嵌入内容同时存在,src 下载执行,嵌入内容不被解析
-
type: 标明内容类型(MIME 类型),默认 text/javascript
- 其他 application/x-javascript,application/javascript,application/ecmascript
2.3 文档模式
- 混杂模式
- 标准模式
2.4 <noscript>
早期浏览器不支持脚本 / 脚本被禁用时显示,使用 noscript 平稳退化
<body>
<noscript> 您的浏览器不支持脚本 / 脚本被禁用 </noscript>
</body>
2.5 PS:
1. async 和 defer 区别?
蓝色线代表网络读取,红色线代表执行时间,均针对脚本;绿色线代表 HTML 解析。
- 默认,同步,顺序解析,解析到立即加载,加载完立即执行。
- defer,异步,同时加载,html 解析完成后执行(多个,不一定按顺序执行,适用外链脚本)(HTML5 要求按出现顺序执行,但实际不一定,不一定会在 DOMContentLoaded 事件触发前执行)
- async,异步,同时加载,加载完立即执行(多个,乱序执行)
2. XHTML 和 HTML 主要不同?
- 元素必正确嵌套,防止 <a><b></a></b>
- 单标签 < />、双标签 <> </> 签闭合
- 标签名、属性大小写敏感
- 必须有根元素
三、基本概念
3.1 ECMAScript 语法
区分大小写
-
标识符:
- 参数,变量,属性,函数名
- 以字母、下划线_、$ 开头
- 惯例为驼峰
- 名称不能为关键字
-
注释:
- 单行注释 / /
- 块级注释 /* */
- 严格模式:编译指示 ” user strict “
-
语句:
- 推荐写分号;结尾
- if() 可省略代码块 {} 直接书写语句,但推荐不省略
-
关键字:
- break case catch continue debugger default delete
- do else finally for function if in
- instanceof new return switch this throw try
- typeof var void while with
-
保留字:
- abstract boolean byte char class const debugger double
- enum export extends final float goto implements import
- int interface long native package private protected public
- short static super synchronized throws transient volatile
- 外加 let、yield、eval、arguments
3.2 数据类型
变量:松散类型(可修改值的类型),var 创建时有作用域
- 只定义未初始化,值为 undefined
- 不推荐在局部中定义全局变量
数据类型:
- 简单(基本)数据类型:number,string,Boolean,undef,null
- 复杂数据类型:Object
typeof 操作符:
- 值:number,string,boolean,undefined,null,object,function
- 特殊情况:typeof null —> object 被认为是空对象指针
对象:
- 空对象,初始化时 obj = null 通过 obj != null 来看是否保存对象引用
- 新建对象:new Object() 或 new Object
布尔:
- true false 区分大小写
数值:
- 八进制(严格模式下失效),0 开头,后续值超过 7 则 079 无效,解析为 79
- 十六进制,不区分大小写,0x 开头欧,后续 0 -9、A-F
- 科学计数法,123e7 或 123e-7,浮点数最大精度 17 位小数
- 浮点数进行计算,结果不准确
- 数值范围 Number.MIN_VALUE 5e-324 ~ Number.MAX_VALUE 1.7976931348623157e+308,超出对应±infinity
- NaN,返回不为数值,也为数值类型,不影响代码执行,操作 NaN 都返回 NaN,与任何值都不相等
字符串:
- 0 或多个 16 位 unicode 字符组成
- 单双引号无区别
- 字符字面量:\n \t \b \r \f \\ \’ \” \x \u 及 6 位 unicode 字符
- 一旦创建,值不可改变,只能 —-> 新的创建,销毁原来的(旧版浏览器执行速度慢)
3.3 方法
数值
- isNaN()隐式转换数值
- Number(),null —-> 0,undefined —> NaN,八进制前导 0 失效,十六进制转换为十进制整数
- parseInt(),直到不是数字,保留整数,识别八进制、十六进制,可指定第二个参数 parseInt(a,8)指定八进制
- parseFloat(),不解析前导 0,可用于:科学计数法转完全展示
字符串:
- toString(a)参数可设置进制,数据转换值,有些不能转换(undefined,null)
- String()遵循先按 toString 执行,不成功再按 String()转换(undefined—-> undefined , null —-> null)
对象:
- constructor 创建实例的函数(构造函数)
- hansOwnProperty 检查当前对象中存在某属性(不查原型)
- isPrototypeOf 检查是否是某对象的原型
- propertyIsEnumerable 能否使用 for-in 枚举
- toLocaleString 返回对象字符串表示
- toString() 对象的字符串表示
- valueOf() 返回对象的字符串、数值或布尔值
3.3 操作符
算数、位、关系、相等操作符
一元操作符(隐式转换):
- 只能操作一个值
- 前置(副效应:语句被求值前值改变)
- 后置(语句被求值后值改变)
- 含对象,执行 valueOf() 后得到的值进行加减
位操作符:
- 转换为 32 位整数,31 位二进制数 + 1 位符号位(0 正 1 负)
- 按位非 ~ 得到值的负值 – 1(底层操作,比 – a – 1 快)
- 按位与 & 二进制每位相与得出二进制值
- 按位或 | 二进制每位相或得出二进制值
- 按位异或 ^ 两位相异则为 1,否则为 0
- 左移 << 移动后补 0,不影响符号位
- 右移 >> 保留符号位,移动后补 0
- 无符号右移 >>> 不保留符号位,负数一般右移后很大
布尔操作符:
- 非!
- 与 && 短路操作(有 false 则不往下执行),null 返回 null,NaN 返回 NaN,undefined 返回 undefined
- 或 || 短路操作(有 true 则不往下执行)
乘性操作符:
- 隐式转换为数值后计算,/ 除法,% 取余
加性操作符:
- + 加法,– 减法
关系操作符:
- <、>、<=、>=
- 都为字符串时,比较字符串字符编码值
- 有对象,转 valueOf(),不成则 toString()
- 字符串比较,大写小于小写,如需比较可全转小写
- 都为字符串的数字,则按编码比
- 一个数字一个字符串,会转为数值
- 转换出 NaN,则结果 false
相等操作符:
- 强制转换规则:有布尔转为数值、有数有字符串转为数值
- 只有一个对象,按照 valueOf()转换后比较
- null == undefined,null !== undefined
- 两个对象,比较是否指向同一对象
条件操作符:条件?‘真,取值’:‘假,取值’
赋值操作符:
- =、+=、*=、/=、%=、<<=、>>=、>>>=(简化书写,不影响性能)
逗号操作符:
- 分隔多个操作
- a =(1,2,3,4),a 值为最后一个 4
3.4 PS:
1. typeof 与 toString
《javascript 高级程序设计》笔记:valueOf() / toString() 对比
2. 负数的二进制表示:
- 绝对值的二进制码,按位取反,加 1,得到
3. 按位非运算符 ~
function fast() {
let s = 2222222222;
let start1 = Date.now();
for (var i = 1; i<10000000000;i++) {s = ~ s};
console.log('fast',Date.now() - start1);
};
function slow() {
let s = 2222222222;
let start2 = Date.now();
for (var i = 1; i<10000000000;i++) {s = - (s + 1) };
console.log('slow',Date.now() - start2);
};
fast();
slow();
相差 4 - 5 秒左右,底层运算更快
4. && || 操作
let d = {name: ‘aa’} ,?? 代表某参数
- d && ?? 返回??
- ?? && d ?? 为 true 返回 d,否则返回??
- 有 null NaN undefined 返回 对应 null NaN undefined
- d || ?? 返回 d
- ?? || d ?? 为 false 返回 d
- d || e 返回 d
- 都是 null NaN undefined 返回 对应 null NaN undefined
3.5 语句
- if(条件){代码块}
- do-while 后测试循环语句,while 中满足则执行
- while 前测试循环语句
- for:while 做不到,for 也做不到、for(; ;)三参数可选
- for-in 循环对象属性,顺序不可预测
- label 名字:语句,结合 for 循环,方便 continue 名字 执行该操作,break 名字 中断名字操作
- break continue
- with 将代码作用域设置到特定对象中,影响性能,不建议使用
with(location){
var t = search.name;
var w = hostname;
}
// 等同于
var t = location.seatch.name;
var w = location.hostname;
- switch 全等比较(不进行类型转换),可以合并情况,case 可为变量、表达式,
switch (i) {
case 25:
/* 合并两种情形 */
case 35:
alert("25 or 35");
break;
...
}
3.6 函数
function(参数){函数体}
- 定义的参数个数可以≠传入参数个数,适用传参个数不定执行不同操作
- 可 function acc(a)传 acc() 或 function acc()传 acc(1,2)
- 内部可用 arguments 来访问参数,如果 a 对应 arguments[0],两值内存空间独立,但互相同步
- 没有重载:函数没有签名,同名函数后定义的生效
读取这两个值会访问相同的内存空间;它们的内存空间是独立的,但它们的值会同步。但这种影响是单向的:修改命名参数不会改变 arguments 中对应的值。另外还要记住,如果只传入了一个参数,那么为 arguments[1]设置的值不会反应到命名参数中。这是因为 arguments 对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。
书中:修改命名参数不会改变 arguments 中对应的值。 实际改变 arguments[0]会同步 a,改变 a 也会同步 argumenets[0]