cookie
默认的有效时间为-1,不设置过期时间时,在浏览器会话结束时过期。
重绘和回流
原型链01
function A() {
this.do = function () {
return 'foo'
}
}
A.prototype = function () {
this.do = function () {
return 'bar'
}
}
var x = new A().do(); // 'foo'
new运算符对函数A进行构造调用,首先创建一个空对象,然后将this指向这个对象,再执行函数A中的代码,最后返回这个对象。A.prototype=重写了函数A的原型,所以如果当函数A中没有定义do()时,下面的运行结果将是xxx is not a function。
原型链02
function A(x) {
this.x = x;
}
A.prototype.x = 1;
function B(x) {
this.x = x;
}
B.prototype = new A(); // new A();并没有给A的原型链上的x赋值
var a = new A(2); // a.x = 2; a.__proto__.x = 1;
var b = new B(3); // b.x = 3; b.__proto__ = B.prototype = { x: undefined }
delete b.x; // 删除的是对象b上的属性x
console.log(a.x); // 2
console.log(b.x); // 读的是原型链上的x:undefined
总结原型链
闭包和内存堆栈
function test() {
var n = 4399;
function add() {
n++;
console.log(n);
}
return {n: n, add: add}
}
var result = test();
var result2 = test();
此时,result和result2都形成了各自的内存堆栈,有各自的闭包,两个互不相干,我在这里容易搞错,以前以为是result和result2同时引用了函数test中的n,实践表明并不是。
关于this指向
var user = {
count: 1,
getCount: function () {
return this.count;
}
}
var func = user.getCount;
console.log(func()); // undefined
func只引用了赋值给user.getCount变量的匿名函数的内存地址,执行func()时,其实是window.func()此时匿名函数中的this为window,并没有变量count,所以打印出来的就是undefined。
自运行函数
自运行函数中var声明的变量不会提升到全局作用域中。
// 自运行函数前一般会加上一个;分号,避免产生一些其它问题
;(function() {
var a = 1;
console.log(a);
})()
console.log(a); // ReferenceError: a is not defined
let变量声明的暂时性死区
let x = 10;
let foo = () => {
console.log(x);
let x = 20;
x++;
}
foo();
只要块级作用域内存在
let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。——《ES6入门》
就是说不会在块级作用域之上的作用域中寻找变量。
浮点数取整
var a = 10.42;
parseInt(a); // 取整数,默认为十进制,10
Math.floor(a); // 向下取整,10
Math.ceil(a); // 向上取整,11
a.split('.')[0]; // 字符串才有鬼split方法,报错
匿名函数赋值给变量和命名函数
var foo = function (x, y) {
return x - y;
}
function foo(x, y) {
return x + y;
}
var num = foo(1, 2); // -1
命名函数和var一样会被提升到代码的最前面,而匿名函数赋值给变量则只在代码执行到该行时才赋值给变量,所以num输出-1。
事件循环
for循环
for循环中包含四个部分:
// var i = 0 为初始化表达式
// i < 10 计算条件的值
// i++ 更新表达式
// 循环体
for(var i = 0; i < 10; i++) {
console.log(i); // 0~9
setTimeout(() => {
console.log(i);
}, 10)
}
// 因为循环到i=9是符合条件,所以更新了表达式,最终i=10
console.log(i); // 10
运算符
JavaScript拥有如下运算符:
赋值运算符。
比较运算符。
算数运算符。
位运算符。
逻辑运算符。
字符串运算符。
条件(三元)运算符。
逗号运算符。
对两个操作数进行求值并返回最终操作数的值。它常常用在
for循环中,在每次循环时对多个变量进行更新。一般出现在
for循环中的初始化表达式和更新表达式中。一元运算符。
void、delete、typeof等关系运算符。
in、instanceof等
function out(x) {
var temp = 2;
function inside(y) {
// ()圆括号运算符优先级最高,递减运算符--后置,则返回递减前的值,反之则是递减之后的值
console.log(x + y + (temp--)); // 3 + 5 + 2 = 10;
console.log(temp); // 1
}
inside(5);
}
out(3);
函数提升
(function () {
var x = foo(); // Uncaught TypeError: foo is not a function
var foo = function foo() {
return "foobar"
};
return x;
})();
具名函数赋值给变量并不会被提升,而且名字只能在函数内部使用(既递归调用)。
冒泡
不支持冒泡的事件:blur、focus、mouseenter、mouseleave、load、unload、resize。
node包引用查找顺序
- 首先加载核心模块(在核心模块中查找)。
- 再是扩展名分析,查找
node_modules中是否有引入的xxx.js文件。 - 没有的话就继续查找
node_modules中是否有xxx文件夹,依次加载其中的index.js、index.node、index.json。 - 还没有找到对应的模块就向上一级目录找。
事件冒泡与捕获
preventDefault();
stopImmediatePropagation();
stopPropagation();
cancelBubbe();
returnValue();
正则表达式的内置方法
正则对象的实例方法:
RegExp.prototype.compile() // 已废弃
RegExp.prototype.exec() // 返回数组或者null,会更新正则对象的lastIndex属性
RegExp.prototype.test()
RegExp.prototype.toString() // 返回一个表示正则的字符串
RegExp.prototype.exec()

图中的index为匹配到的字符位于原始字符串的基于0的索引值。
RegExp.prototype.test()
lastIndex
字符串实例上与正则有关的方法:
String.prototype.match()
String.prototype.matchAll()
String.prototype.replace()
String.prototype.search()
String.prototype.split()
Array.prototype.splice()
[1, 2, 3].splice(1, 1, 1) == [2] // false
上面的方法用自然语义来说:删除数组[1, 2, 3]索引为1开始的元素,总共删除1个,并在索引为1的位置添加一个元素1,最后以数组的形式返回删除的元素。
返回的是[2],但是由于与==后面的[2]并不是一个内存地址,所以为false。