<script>
- defer
<script defer src="example.js"></script>
表示先下载,但等页面渲染完后再执行,从而,这个脚本可以放在<head>中,但仍会阻塞。这意味着脚本执行的时候不会改变页面结构,推迟后他们按顺序执行 - async
<script async src="example.js"></script>
表示不需要等待其他脚本,同时也可以不阻塞文档渲染,不能确保按顺序执行(下载后就执行)
let and var P25
var:函数作用域
let: 块作用域
暂时性死区
例子
for中的var会渗透到外部,而let不会声明风格
优先const 再者let
数据类型
number P37
parseInt、parseFloat函数String P40
toString 可以传参转换进制
${}插值
*es6新增:模板字面量
可以跨行,主要用于定义HTML模板(template)
.raw方法获取原始字符-
Symbol
let test = Symbol
使得test成为一个唯一标志
可以添加描述let test1 = Symbol('test')
let test2 = Symbol('test')
此时test1!=test2
Symbol不是构造函数-
全局符号注册表:
如果需要test1===test2,即共享符号,使用
let test1 = Symbol.for('test')//创建新符号
let test2 = Symbol.for('test')//重用该符号
此时test1===test2
搭配Symbol.keyFor()查询注册符号 - P49 暴露内部方法与修改:https://segmentfault.com/a/1190000019870195
举例:instanof操作符使用的就是Symbol.hasInstance方法,该方法定义在Function的原型上
采用Symbol.xxx可以避免使用字符串解析从而增加特殊字符(开辟新天地)Symbol.hasInstance本身就是一个方法名,在Function内部的原型中它写了如何进行判断原型链,我们可以改写它
-
全局符号注册表:
//[]相当于. 而前者可以使得变量解析为对应键
<script type="text/javascript">
let fun = function(){
}
console.log(fun.__proto__[Symbol.hasInstance])
//别忘了__proto__它指向构造器
console.log(Function.prototype[Symbol.hasInstance])
console.log(fun.__proto__[Symbol.hasInstance]===Function.prototype[Symbol.hasInstance])
console.log(Symbol)
</script>
- Object
每个object实例都有以下属性和方法(在__ proto__即Object.prototype上)- constuctor:它就是构造器函数
- hasOwnProperty:检查当前对象上是否存在给定属性(能分辨属性是否在原型上)
- <xxx(函数).prototype>isPrototypeof:判断当前对象是否为另一个对象(构造器函数)的原型
- ...
重要操作符以及语句
- 位操作符 P60
在JS中无论是整数还是小数都是按照64位的浮点数形式存储,而整数运算会自动转化为32位有符号整数。
(即:整数运算无法算64位的)
其中,前31位表示出了整数值,第32位表示数值符号
正值以真正的二进制存储,而负值以“二补数”的形式储存
这里的位指位模式,每个位只储存0和1,通过不同幂权决定十进制实际值
使用位运算将从数值的底层表示上进行操作 因此速度快得多
- 加法运算常见错误
有任一操作对象为字符串,则将另一个操作转化为字符串进行拼接
`let result = 5+"5"//result是"55"
let num1 = 5,num2 = 10;
let message = "The sum of 5 and 10 is" + num1+num2;//结果是510而不是15
//(num1+num2)即可解决
全等与不全等
不全等指转换后相等
"55"==55;//true"55"===55;//false
for-in、for-or
前者用于枚举对象中的非符号化键属性
后者用于枚举数组元素
还有for-await-of这种东西不指定返回值的函数会返回undefined
高性能
js阻塞
- 为什么会阻塞?主要是历史原因
以前js经常执行document.write,而导致DOM元素变化,而js在读到js代码时,并不知道这个js代码是否会操作DOM元素,为了能够应对这样错综复杂的插入和修改DOM,js和渲染(包括css)只能单线程执行
现在的浏览器都支持async或者defer属性了,说明脚本非阻塞其实一点问题都没有
css也会造成渲染阻塞,但不会造成解析阻塞css加载会造成阻塞吗
解决方式
- 使用打包工具合并脚本
- 动态脚本元素<script>(async出现之前)
var script = document.creatElement("script")
script.type = "text/javascript"
script.src = "file.js"//此时开始加载,是异步的
document.head.appendChild(script)//加载到head标签里,通常会立即执行
//一般情况下封装为loadScript(url,callback);(利用script.onload事件执行回调)
注意,加载后会立即执行
上述过程是异步的,也就是说默认为async,可以手动取消使之顺序执行
- 更进一步使用XMLHttpRequest()脚本注入
它可以下载但延缓执行
局限(还不懂):js文件作用域必须和页面相同,这意味着不能从CDN下载
- 无阻塞脚本
- defer: 用于不依赖DOM的脚本,这让浏览器同步下载,但等待页面渲染完后再执行
注意:- defer不是在最后一行后紧接着执行的,而是在onload事件处理器
window.onload = function()
前执行
defer 特性仅适用于外部脚本
- defer不是在最后一行后紧接着执行的,而是在onload事件处理器
- async: 完全异步加载,但不能确保顺序 算是最佳实践
- defer: 用于不依赖DOM的脚本,这让浏览器同步下载,但等待页面渲染完后再执行