1. 浏览器内核
- IE – trident
- Chrome – webkit/blink
- firefox – Gecko
- Opera – presto
- Safari – webkit
2. 数据类型
- 原始值 (栈)
- Number Boolean String undefined null
- 引用值 (堆)
- array object function
- js中布尔值为false的六种情况 (转化为Boolean)
- 0, ”, null, undefined, NaN,false
- 其他都是true
- 逗号运算符
- (e1,e2) 返回的是e2
3. 基本语法
- js语法错误引发当前代码块终止,但不会影响其他代码块的终止
4. 操作符 (运算符就是求结果)
- 任何字符串相加都是字符串,从左往右,“视觉上链接”
- NaN, Infinity –> Number 类型
- 字符串比较的是ASCII码顺序,A->65, a->97
- Infinity == Infinity (true), NaN == NaN (false,不等于任何东西)
- && (e1 && e2)
- 碰到假的直接返回那个假的表达式的结果,如果全都为真,返回最后一个表达式的结果
- && 可以当做短路语句,当做if-else来用,e1和e2可以是语句,表达式
- || (e1 || e2)
- 碰到真的直接返回那个真的表达式的结果,如果全都为假,返回最后一个表达式的结果
- for (e1;e2;e3)
- 先执行e1,在判断e2,然后执行循环体,最后e3,当然e2不成立的时候,结束循环
- ~ 位非操作符 (~1)
- 将1(这里叫:原码)转二进制 = 00000001
- 按位取反 = 11111110
- 发现符号位(即最高位)为1(表示负数),将除符号位之外的其他数字取反 = 10000001
- 末位加1取其补码 = 10000010
- 转换回十进制 = -2
- 转化数字为零的话,直接返回-1,其他的是-(X+1)
- 优先级
- . [] ()
- ++ — – ~ !
- * / %
- + – +
- << >> >>>
- < <= > >= instanceof
- == != === !==
- &&
- ||
- , 多重求值
5. typeof
- Number Boolean String Object Function undefined
6. 类型转化
- Number (undefined) -> NaN (Number 转不了的东西都返回NaN), null ->0, Infinity – >Infinity,包括转化小数,范围比parseInt大
- parseInt (true,false,null,undefined,NaN等) 全部转化为NaN
- String 可以转化任何东西,但toString不能转化 undefined和null,可以接受一个参数,转化为相应的进制
- String({}) — [object Object]
- String(null) — null
- String(一个函数) — 字符串的函数体
- String([]) — ”
- isNaN – 先做Number() 转化,然后在判断NaN
- + 两边没有字符串就是数字相加,否则就是字符串相加
- ++、–、+/- 先做Number() 转化
- Number({}) NaN
- Number([]) 0
- {} + [] 0, {} 是代码块,执行空代码块,+是正负不是字符串连接符号
- [] + {} ‘object Object’
- + 加号,隐式转化 string
- typeof(a) a 没有定义的情况下,返回undefined 只有这种情况不报错
- 当number 参数为对象的时候,执行toPrimitive操作,toPrimitive 操作先检查是否有valueOf方法,如果它返回的不是对象值,就直接返回,如果是的话,就执行toString方法,返回toString的返回值
7. 函数
- 函数也有length,代表函数形参的个数
8. 预编译(三部曲)
- 通篇扫描,语法分析
- 预编译 (函数声明整体提升,变量提升),发生函数执行的前一刻
- 函数声明提升到最前面
- 变量声明到前面
- 函数声明优先级高于变量声明
- 预编译执行过程
- 创建AO对象(执行期上下文)
- 找形参和变量声明,讲形参和变量作为AO属性名,值为undefined
- 将实参和形参统一
- 在函数体内找函数声明,赋值与函数体
- 全局会生成GO对象
- 解释执行
9. 作用域链条 [[scope]],函数的作用域链[[scope]]
- [[scope]]是作用域
- 运行期上下文,当函数执行时,会创建执行器上下文的内部对象AO,每次执行时,对应的执行器上下文都是独一无二的,当函数调用完毕的时候,执行上下文被销毁
- 查找变量,从作用域连的顶端依次向下寻找
- 从函数的作用域链顶端开始查找
10. 闭包
- 但凡是内部的函数被保存到外部进行访问,一定形成闭包
- 闭包会导致作用域链不释放 造成内存泄露 – 缺点
- 闭包作用
- 实现公用变量
- 函数累加器,执行一次加一次
- 可以做缓存 存储结果
- 相当于全局变量存储
- 私有变量
- 模块化开发,防止全局变量污染
- 实现公用变量
11. 立即执行函数
- 此类函数没有声明,在一次执行后立即释放,适合做初始化工作
- (function(){}()) – w3c, (function(){})()
- 只有表达式才能被执行符号执行,执行符号就是()
- 能被执行符号执行的表达式,函数名自动忽略
12. 对象
- 对象创建方法
- var a = {}, b = {name:1}, a[b] = 20, b会转化成字符串'[object Object]’
var obj = {} //对象字面量
var obj = new Object() //构造函数
function Student(){
//var this = {
//__proto__:Person.prototype
}
this.name = 'a';
return {}; //不能return 123,系统会自动忽略原始值 在new的情况下
//return this;
}
var s = new Student();
原始值是不能有属性和方法的
var num = 3;
num.len = 4;
conosle.log(num.len) //undefined
//new Number(3).len = 4; delete 相当于隐式调用了这个
//属性能能赋值,但是返回undefined
13. 原型
- 原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过构造函数产生的对象,可以继承原型的属性和方法。原型也是对象
- 可以提取公共属性
- 隐式属性 __proto__
- 对象的构造函数 constructor
- 不能通过对象修改原型prototype,如果是引用值是可以修改的,相当于调用修改
- 所有对象都是继承Object.prototype
- Object.create(null) 没有原型
- call/apply
- 作用,改变this指向
- 区别,参数不同
- 任何方法都可以call
- 借用你的方法,实现我的功能
- test() 实际上是执行 test.call()
function Person(name){
//this = obj
this.name = name;
}
var obj = {};
Person.call(obj); //this = obj 改变this对象值
14. 继承
- 原型链
- 借用构造函数
function Person(name,sex){
this.name = name;
this.sex = sex;
}
function Student(name,sex,age){
Person.call(this,name,sex);
this.age = age;
}
var student = new Student('a','male',12);
共享模式 (共有原型)
Father.prototype.lastName = 'liu';
function Father(){
}
function Son(){
}
Son.prototype = Father.prototype;
圣杯模式
//通过中间件
function F(){}
F.prototype = Father.prototype;
Son.prototype = new F();
15. 命名空间
- 管理变量,防止污染全局,适合模块化开发
- in 和 hasOwnProperty 区别在于,in判断嫩不能访问到,hasOwnProperty只会判断对象本身里面的属性,不会去判断原型里面的属性
- 每一个对象都有隐式__proto__对象属性,是原型链
- constructor是属于原型的属性
- instanceof
- A instanceof B -> A对象是不是B构造函数构造出来的 (官方给的)
- A instanceof B 看A的原型链上有没有B的原型
- 区分 [] 和{}
- instanceof
- constructor
- Object.prototype.toString.call([])
16. 数组
var arr1 = [10];
var arr2 = new Array(10); //长度为10的undefinedx10 的数组
var arr3 = new Array(1,2,3,4);//长度为4 元素1,2,3,4
改变原数组的方法(9个): https://www.jb51.net/article/141330.htm
let a = [1,2,3];
//ES5:
a.pop()/ a.shift()/ a.push()/ a.unshift()/ a.reverse()/ a.splice()/ a.sort()
//ES6:
a.copyWithin() / a.fill
- 不改变原数组的方法(8个):
- ES5:join、toLocateString、toStrigin、slice、cancat、indexOf、lastIndexOf
- ES7:includes
- ES6 Array.of() 返回由所有参数值组成的数组
let a = Array.of(3, 11, 8); // [3,11,8]
let a = Array.of(3); // [3]
ES6 Arrar.from() 将两类对象转为真正的数组
// 1. 对象拥有length属性
let obj = {0: 'a', 1: 'b', 2:'c', length: 3};
let arr = Array.from(obj); // ['a','b','c'];
// 2. 部署了 Iterator接口的数据结构 比如:字符串、Set、NodeList对象
let arr = Array.from('hello'); // ['h','e','l','l']
let arr = Array.from(new Set(['a','b'])); // ['a','b']
- 遍历方法(12个): js中遍历数组并不会改变原始数组的方法总共有12个:
- ES5:forEach、every 、some、 fliter、map、reduce、reduceRight
- ES6:find、findIndex、keys、values、entries
17. 类数组
- 可以利用属性名模拟数组的特性
- 可以动态增加length的长度
- 如果强行让类数组调用push方法,则会根据length属性值的位置进行属性的扩充
- 数组深拷贝
- JSON.stringfy()和JSON.parse()
- 但是这种简单粗暴的方法有其局限性。当值为undefined、function、symbol 会在转换过程中被忽略
function deepCopy(obj) {
var result = Array.isArray(obj) ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'object') {
result[key] = deepCopy(obj[key]); //递归复制
} else {
result[key] = obj[key];
}
}
}
return result;
}
var obj = {
'0' : 'a',
'1' : 'b',
'2' : 'c',
'length' : 3,
'push' : Array.prototype.push //可选,
'splice' : Array.prototype.splice //可选
}
//类数组的添加
//1.属性为索引 数字
//必须有length,最好有push方法
18. 错误信息 6种
- EvalError
- eval()的使用与定义不一致
- RangeError
- 数值越界
- ReferenceError
- 非法或者不能识别的引用数值
- SyntaxError
- 发生语法解析错误
- TypeError
- 操作数类型错误
- URIError
- URI处理函数使用不当
19. DOM
- 查
- document.getElementsByTagName(‘div’)
- document.getElementById
- document.getElementsByName 只有部分标签可生效 (表单,表单元素,img,iframe)
- document.getElementsByClassName,多个class可以一起 (ie8 以及以下没有该方法)
- querySelector css选择器
- 缺点选出来的元素不是实时的
- querySelectorAll css选择器
- 缺点选出来的元素不是实时的
- nodelist
- 节点类型
- 元素节点
- 属性节点
- 文本节点
- 注释节点
- document
- DocumentFragment
- 元素节点是节点的一部分
- 节点类型
- Dom 树
- document 对象的构造函数是HTMLDocument, 大的Document 是一个函数类,但是不能new
- document -> HTMLDocument.prototype -> Document.prototype (一层一层的继承关系,形成了原型链)
20. 正则表达式
- var reg = /abc/i
- i 表示忽略大小写
- g 全局匹配
- m 多行匹配 var str = ‘aas\naa’ \n表示换行符,这样就可以匹配多行了
- []
- 表达式,一个方括号表达一位 (方括号里面的值表示取值的范围)
- [^]放到表达式里面表示 非
- ()
- (a|b|c) 或 相当于表达式区间
- 元字符 (相当于表达式)
- \w === [0-9A-z_]
- \W === [^\w]
- \d === [0-9], \D === [^\d]
- \s 表示空白字符 空格 换行符 换页符等
- \b 表示单词边界 var str = /abc dfs lop/
- \. === [^\r\n]
- 量词 (贪婪模式,能匹配多的就匹配多的)
- n+ === {1, }
- n* === {0, }
- n? === {0, 1}
- n{x} === {x}
- n{x,y} === {x,y}
- n{x,} == {x,}
- /(a)\1/ 括号子表达式 /(\w\1\1\1)/ 三次匹配子表达式里面的内容 这个能匹配出 xxxx 形式的字符串
21. 事件
- 事件冒泡 (事件模型)
- 结构式的嵌套元素才会冒泡 (自底向上),子元素向父元素传递
- focus,blur,change,submit,reset,select等事件不冒泡
- 事件捕获 (事件模型)
- 结构式的嵌套元素才会冒泡 (自上向底),父元素向子元素传递
- 一个元素只能存在一种事件模式,要么事件冒泡,要么事件捕获
- 触发顺序
- 先捕获,然后冒泡
- 取消浏览器默认行为
- 事件委托
- 在父元素上加事件,通过源对象,冒泡行为解决性能问题
22.其他补充
- console.dir() 可以显示一个对象所有的属性和方法
比较运算符原型链关系图https://www.jianshu.com/p/5c8f3d089fb7
function instanceof_(left, right){
left = left.__proto__
while(left !== right.prototype){
left = left.__proto__ // 查找原型,再次while判断
if(left === null){
return false
}
}
return true
}