一、主流浏览器内核
IE trident
Chrome webkit/blink(2014年以后)
firefox Gecko
Opera presto
Safari webkit
二、js三大部分
1、EMCAScript
2、DOM(document object model) 操作文档对象模型
3、BOM(brower object model) 操作浏览器对象模型
三、原始值
Number String Boolean undefined null
四、引用值
array Object function ...date RegExp
五、值转换Boolean类型
1、undefined,null,NaN, "", 0, false 转为Boolean类型都为false
2、除上面外的所有值转为Boolean类型都为true
六、&&运算
1、先看第一表达式转换成布尔值的结果,如果结果为真,那么它会看第二个表达式转换为布尔值的结果,然后如果只有两个表达式的话,只看第二个表达式,就可以返回该表达式的值了
比如 var = 1 && 2; 结果为2。 var = 1 && 2 + 2; 结果为4
2、第一个表达式为假的话,就返回第一个表达式的值
比如 var = 0 && 2; 结果为0
3、多个表达式的话,结果按1、2的原则处理
比如 var = 1 && 2 && 5; 结果为5。 var = 1 && 0 && 5; 结果为0
七、typeof 获取值类型,总共有下面6种类型
number string boolean undefined function object(array object null)
注意:typeof(typeof(undefined))值为string
八、类型转换
1、Number 转为数字,如果有包含非数字和数字的话,转为NaN
2、parseInt 转为整形,parseInt('123ab'),转为123,就会把数字开头的转为数字,其他舍弃,如果有包含小数位,直接舍去;parseInt('10', 16),转为16,第二位参数是基底,将数字按基底的进制转为10进制数字,基底取值为2~36和0。
3、parseFloat 转为浮点类型
4、toString 转为字符串,undefined和null不能调用toString,不然会报错
5、String 转为字符数
6、Boolean转为布尔值
7、isNaN判断是否非数,原理是将参数用Number进行转换后再与NaN进行比较。isNaN("abc")的值为true
九、函数
1、实参和形参可以不一样,可以在函数里面通过arguments数组获取到实参的数据,当形参和实参有映射关系,即对应的形参对应实参有写的话,通过改变形参的值话,会对应修改arguments对应的值
function sum (a, b) {
arguments[0] = 3;
console.log(a); //3
a = 5;
console.log(arguments[0]); //5
b = 2;
console.log(arguments[1]); //undefined
}
sum(1);
2、递归函数
(1)找规律
(2)找出口
十、预编译
(一)二条现象可解决部分问题
1、函数声明整体提升
2、变量 声明提升
(二)二条准则
1、imply gobal 暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就全局对象所有。
a = 123; ===>window.a = 123;
var a = b = 123;===> a = window.b = 123;
2、一切声明的全局变量,全是window的属性
var a = 123; ===> window.a = 123;
(三)四部曲
1、创建AO对象(Activation Objecct)(执行期上下文)
2、找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
3、将实参值和形参统一
4、在函数体里面找函数声明,值赋予函数体
预编译后
AO {
a: undefined,
b: undefined
}
===>
AO {
a: 1,
b: undefined,
d:function d() {}
}
===>
AO {
a: function a() {},
b: undefined,
d:function d() {}
}
===>
执行后
AO {
a:123,
b: function() {},
d:function d() {}
}
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a () {}
console.log(a);
var b = function () {}
console.log(b);
function d() {}
}
fn(1);
结果:function a() {}
123
123
function () {}
十一、作用域
b函数返回到外部的话,a销毁,a自己的AO和GO作用域链剪断了不存在引用关系,但是b其作用域链还在,,即b还存在a的AO和GO对象的引用,所以b包含a的num的引用,demo函数每次执行只是会创建新BO,但是AO和GO不会重新创建,所以num值一直在
function a() {
var num = 100;
function b() {
num ++;
console.log(num);
}
return b;
}
var demo = a();
demo(); //101
demo(); //102
十二、立即执行函数
1、应用场景:针对初始化功能的函数,只被调用一次就释放
2、只有表达式才能被执行符号执行
3、立即执行函数就会忽略函数名,执行完后,函数名访问就是undefined
(function () {} ())
十三、闭包
1、当内部函数被保存到外部时,将会生成闭包。
2、闭包会导致原有作用域链不释放,造成内存泄露。
3、作用
(1)实现公有变量,比如累加器
function add() {
var num = 0;
function a() {
console.log(++num);
}
return a;
}
var myAdd = add();
myAdd();
myAdd();
myAdd();
(2)可以做缓存(存储结构)
function test() {
var food = "apple";
var obj = {
eatFood : function () {
if(food != "") {
console.log("I am eating " + food);
food = "";
} else {
console.log("There is nothing!");
}
},
pushFood : function (myFood) {
food = myFood;
}
}
return obj;
}
var person = test();
person. eatFood();
person. pushFood(''banana");
person. eatFood();
(3)可以实现封装,属性私有化
(4)模块化开发,防止污染全局变量
4、闭包造成的问题,需用闭包来解决
function test () {
var arr = [];
for (var i = 0; i < 10; i++) {
arr[i] = function () {
console.log(i);
}
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++) {
myArr[j](); //都是10
}
//修改成下面就能达到预期结果
function test () {
var arr = [];
for (var i = 0; i < 10; i++) {
(function (j) {
arr[j] = function () {
console.log(j);
};
}(i))
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++) {
myArr[j]();
}
十四、构造函数内部原理
1、在函数体最前面隐式的加上this={ proto : 对象名.prototype },proto可以被修改
2、执行this.xxx = xxx;
3、隐式返回this
十五、对象、包装类
var str = "abc";
str += 1; // "abc1"
var test = typeof(str); //"string"
if (test.length == 6) { //true
test.sign = "typeof的返回值可能为String"; // new String(test).sign = "typeof的返回值可能为String"; 由于没赋值,所以test.sign运行完就销毁了
}
console.log(test.sign); //new String(test).sign,结果为undefined
function Person(name, age, sex) {
var a = 0;
this.name = name;
this.age = age;
this.sex = sex;
function sss() {
a ++;
console.log(a);
}
this.say = sss;
}
//由于sss函数过载在say方法并被保存在外部,所以a变量在同一个对象中是公用的
var oPerson = new Person();
oPerson.say(); //1
oPerson.say(); //2
//由于从新new一个对象,a变量也是新的一份
var oPerson1 = new Person();
oPerson1.say(); //1
var x = 1, y = z = 0;
function add(n) {
return n = n + 1;
}
y = add(x);
function add(n) {
return n = n + 3;
}
z = add(x);
预编译函数提升,后面同名的函数会覆盖前面的同名函数
console.log(''x=",x); //1
console.log("y=",y); //4
console.log("z=",z); //4
十六、原型、原型链,call/apply
1、并不是所有的对象都继承Object.prototype,通过Object.create(null)创建出来的对象就没有
2、 call/apply 共同点改变this指向,不同点传参方式不同
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex.= sex;
}
function Stundet(name, age, sex, tel, grate) {
Person.call(this, name, age, sex);
this.tel = tel;
this.grate = grate;
}
var student = new Stundet('sunny', 123, 'male', 139, 2007);
十七、继承模式,命名空间,对象枚举
1、圣杯模式
var inherit = (function () {
var F = function () {}; //只是起到中间变量,通过闭包私有化
return function (Target, Origin) {
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
2、A instanceof B,看A对象的原型链上有木有B的原型,如果有的话就是true,反之为false
3、区别一个变量res是数组还是对象的三种方法
(1) res.constructor来区分
(2) 通过instanceof, res instanceof Array,如果为true就是数组,反之为对象
(3)通过Object.prototype.toString.call(res),如果为"[object Array]"的话,就是数组,反之为对象
十八、this
1、函数预编译过程this -> window
2、全局作用域里this -> window
3、call/apply可以改变函数运行时this指向
4、obj.func(); func()里面的this指向obj
var name = "222";
var a = {
name : "111",
say : function() {
console.log(this.name);
}
}
var fun = a.say;
fun(); // 222,由于没有谁调用,所以当前this是window
a.say(); //111, 由于a调用,所以this指向a对象
var b = {
name : "333",
say : function (fun) {
fun(); //没有谁调用,所以当前this是window
}
}
b.say(a.say); // 222
var foo = 123;
function print() {
this.foo = 234;
console.log(foo);
}
print(); //234,由于没被谁调用,所以当前this指向window,所以foo的值被改为234
new print(); //123,由于new后,this = Object.create(print.prototype),所以全局的foo值没有被改变,仍为123
var a = 5;
function test() {
a = 0;
alert(a);
alert(this.a);
var a;
alert(a);
}
test(); // 0, 5, 0; this = window
new test(); // 0, undefined, 0; this = Object.create(test.prototype)
arguments.callee指向函数自身引用
// 求100的阶乘
var num = (function (n) {
if (n == 1) {
return 1;
}
return n * arguments.callee(n - 1);
}(100))
十九、深拷贝
1、判断是不是原始值 (typeof 判断是不是object,然后再对null特殊处理)
2、判断是数组还是对象(建议用toString)
3、建立相应的数组或对象
function deepClone(origin, target) {
var target = target || {},
toStr = Object.prototype.toString,
arrStr = "[object Array]";
for (var pro in orgin) {
if (origin.hasOwnProperty(prop)) {
if(origin[prop] !== "null" && typeof(origin[prop]) == 'object') {
target[prop] = toStr.call(origin[pop] == arrStr ? [] : {};
deepClone(origin[prop], target[prop]);
} else {
target[prop] = origin[prop];
}
}
}
return target;
}
二十、数组常用的方法
1、改变原数组push, pop, shift, unshift, sort, reverse, splice
2、不改变原数组concat, join -> split, toString, slice
二十一、类数组(同时满足以下条件就是类数组)
1、满足有索引(key为数组)
2、满足有length字段
var obj = {
"2" : "a",
"3" : "b",
"length" : 2,
"push" : Array.prototype.push
// ,"splice" : Array.prototype.splice //有加splice的话,console.log(obj)输出的就变为数组
}
obj.push('c');
obj.push('d');
console.log(obj); //结果为{2: "c", 3: "d", length: 4}
//数组的push原理
Array.protptype.push = function (target) {
obj[obj.length] = target;
obj.length ++;
}
二十二、Error.name的六种值对应的信息
1、EvalError: eval()的使用与定义不一致
2、RangeError: 数值越界
3、ReferenceError: 非法或不能识别的引用数值
4、SyntaxError: 发生语法解析错误
5、TypeError: 操作数类型错误
6、URIError: URI处理函数使用不当
二十三、插件
1、ement html插件
二十四、Dom
(一)节点的类型
1、元素节点
2、属性节点
3、文本节点
8、注释节点
9、document
11、DocumentFragment
(二)获取节点类型nodeType
(三)获取css样式
1、获取行间样式
ele.style.prop //可读可写
2、查询计算样式
window.getComputedStyle(ele, null) //第一个参数是元素,第二个参数是伪元素,不是获取伪元素就填null
二十五、事件处理模型
1、事件冒泡:结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)
2、事件捕获:结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自顶向下)
3、触发顺序:先捕获后冒泡
4、focus,blur,change,submit,reset,select等事件不冒泡
二十六、js加载时间线
1、创建Document对象,开始解析web页面。解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中,该阶段document.readyState = 'loading'。
2、遇到link外部css,创建线程加载,并继续解析文档。
3、遇到script外部js,并且没有设置async、defer,浏览器加载,并阻塞,等待js加载完成并执行该脚本,然后继续解析文档
4、遇到script外部js,并且设置async、defer,浏览器创建线程加载,并继续解析文档,对于async属性的脚本,脚本加载完成后立即执行。(异步禁止使用document.write());
5、遇到img等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档。
6、文档解析完成,document.readyState = 'interactive'。
7、文档解析完成后,所有设置有defer的脚本会按照顺序执行。(注意与async的不同,但同样禁止使用document.write())
8、document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转为事件驱动阶段
9、当所有async的脚本加载完成并执行后、img等加载完成后,document.readyState = 'complete',window对象触发事件。
10、从此,以异步响应方式处理用户输入、网络事件等。
document.addEventListener('DOMContentLoaded', function () {
console.log('文档解析完成了,可以操作dom树了');
var div = document.getElementsByTagName('div')[0];
console.log(div);
}, false)
二十七、正则表达式
1、将aabb变成bbaa
var reg = /(\w)\1(\w)\2/g;
var str = "aabb";
console.log(str.replace(reg, "$2$2$1$1")); //bbaa
str.repace(reg, function ($, $1, $2) { //参数1全局匹配结果,参数2第一子表达式匹配结果,参数3第二个子表达式匹配结果
return $2 + $2 + $1 + $1
}) //bbaa
2、将the-first-name变为theFirstName
var reg = /-(\w)/g;
var str = "the-first-name";
str = str.replace(reg, function($, $1) {
return $1.toUpperCase();
});
3、将100000000变为100.000.000
var str = "100000000";
var reg = /(?=(\B)(\d{3})+$)/g;
str = str.replace(reg, ".");
4、reg.exec()和reg.lastIndex配合使用,lastIndex当前游标,只有当有g的时候才有效果,不然都是0,到最后一位的话,会重新从0开始
网友评论