乐趣区

JavaScript高级程序设计笔记基本概念

一、写在前面

最近重读《JavaScript 高级程序设计》,总结下来,查漏补缺。

二、JS 简介

2.1 JS 组成

  • ECMAscript:以 ECMA-262 为基础的语言,由浏览器支持
  • DOM:编程接口(API), 将页面映射成节点结构(文档树),提供操作方法
  • BOM:浏览器对象模型,处理浏览器窗口和框架交互(部分扩展)

2.2 <script>

  • 实现在 HTML 中插入 JS
  • 内嵌,外联(好处:可维护,可缓存,适应未来)
  • 推荐放在 body 中、内容后,缩短内容呈现时间(浏览器遇到 body 呈现内容)

参数:

  1. async: 立即下载脚本(外部文件),异步执行

    • 不保证按出现顺序执行
    • 多个 async 时,保证互不依赖,建议无修改 DOM 操作
    • 在页面 load 前执行,不一定在 DOMContentLoaded 事件触发前执行
  2. charset: 指定代码字符集(很少用,部分浏览器忽略该参数)
  3. defer: 下载后延迟执行,文档完全解析显示后执行

    • 延迟脚本,延迟到 </html> 后执行,页面 load 前执行
    • 最好只有一个延迟脚本(HTML5 要求按出现顺序执行,但实际不一定按顺序执行,也不一定会在 DOMContentLoaded 事件触发前执行)
  4. language: 标明编写语言(废弃)
  5. src: 外部文件及地址链接

    • src、标签间嵌入内容同时存在,src 下载执行,嵌入内容不被解析
  6. 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 语法

区分大小写

  1. 标识符:

    • 参数,变量,属性,函数名
    • 以字母、下划线_、$ 开头
    • 惯例为驼峰
    • 名称不能为关键字
  2. 注释:

    • 单行注释 / /
    • 块级注释 /* */
  3. 严格模式:编译指示 ” user strict “
  4. 语句:

    • 推荐写分号;结尾
    • if() 可省略代码块 {} 直接书写语句,但推荐不省略
  5. 关键字:

    • 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
  6. 保留字:

    • 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]

退出移动版