// 1
let result1 = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false;
console.log(result1);
// NaNTencentnull9false
// 2
let a = "?";
if (a == 1 && a == 2 && a == 3) {
console.log("OK")
};
/*
let a = {
num: 0,
toString: function () {
return this.num += 1;
}
};
*/
// 3
let arr = [27.2, 0, '0013', '14px', 123];
result3 = arr.map(parseInt);
console.log(result3);
// 27,NaN,1,1,27
let a = 123;
function fn1(){
console.log(a);
}
function fn2(){
let a = 456;
fn1();
}
fn2(); // => 123
// function 和 全局变量一样都被提前声明,函数保存了父级环境,
// 在fn2中调用fn1会在自身作用域下寻找a,如果没有会向上寻找父级作用域,其父级为全局
for (let i = 0; i < 5; i++) {
setTimeout(function()) {
console.log(i);
});
}
// => 01234
// 上面的for意思是利用循环开启了5个定时器 即使定时器不会立刻执行
// 但let定义的变量存在自己的作用域最后还是输出01234
for (var i = 0; i < 5; i++) {
setTimeout(function()) {
console.log(i);
});
}
// => 55555
// 计时器是异步进行的定时器是异步执行的
// 下面的for循环也是用循环开启5个定时器,但是定时器不会立刻触发,由于定时器是异步执行的
// 所以当for循环执行完才会触发定时器,for循环执行完i的值会变成5,并且最后的i值会覆盖前面的值所以是55555
if (! "a" in window) {
console.log("a");
var a = 1;
}
if (! "b" in window) {
console.log("b");
let b = 1;
}
console.log(a); // undefined
console.log(b); // Uncaught ReferenceError: b is not defined
闭包,保存一份变量
function fun () {
var i = 0;
return function () {
console.log(i++);
}
}
var f1 = fun();
var f2 = fun();
f1(); // 0
f1(); // 1
f2(); // 0
// f1、f2 产生闭包,各自保存一份变量 先打印再自增
// f1调用两次 里面i是闭包保存的同一个i,所以第二个打印1,当然打印1后i=2
f1() // 2
命名函数只能在函数自身内部使用,在外使用会报错
var foo = function bar() {
return 123;
};
console.log(typeof foo); // function
console.log(typeof foo()); // number
console.log(typeof bar()); // error
console.log(typeof bar); // error
// 第三个命名函数只能在函数自身内部使用,在外使用会报错
console.log(foo);
console.log(foo());
console.log(bar());
console.log(bar);
this(除箭头函数)永远指向当前正在运行的对象
即:非箭头函数指向调用它的对象,就是离它最近的,箭头函数本身没有this,其this指向离它最近的非箭头函数的作用域
var obj = {
a = 1,
foo: function() {
return this.a;
}
}
var fun = obj.foo;
console.log(obj.foo()); // 1 this=>obj
console.log(fun()); // undfined 复制了fun的方法,该方法调用实质是挂载到window上,window并未声明a
1 直接通过标识符访问变量,首先沿作用域查找每一个变量对象,
直到全局变量对象仍然没有,就沿全局变量的原型链查找
2 通过. 或[] 访问对象中的标识符,就直接沿原型链查找
function A(x) {
this.x = x;
}
function B(x) {
this.x = x;
}
A.prototype.x = 1;
B.prototype = new A();
var a = new A(2);
var b = new B(3);
delete b.x;
console.log(a.x); // => 2
console.log(b.x); // => undefined
// a x = 2
// b x = 3,但是delete删除了自身属性,x的值取原型链上x的值,
// 即new A()时, x = undefined因为未传参
// 1 直接通过标识符访问变量,首先沿作用域查找每一个变量对象,
// 直到全局变量对象仍然没有,就沿全局变量的原型链查找
// 2 通过. 或[] 访问对像中的标识符,就直接沿原型链查找
const obj = {
flag: false,
}
function A() {
this.flag = true;
return obj;
}
const a = new A();
console.log(a.flag); // => false
// new关键字创建一个新对象{},新对象原型链指向构造函数A的prototype,新创建的对象赋值给this,
// 并执行构造函数里面的代码给this做赋值初始化,最后返回创建的对象this。
// 如果构造函数A没有返回值或返回简单类型,则返回this,因为构造函数A返回了obj,所以a===obj
// Function.prototype.__proto__ == Object.prototype
事件循环:微任务和宏任务
每个宏任务之后,引擎会立即执行微任务队列中的所有任务,然后再执行其他的宏任务,或渲染,或进行其他任何操作。
在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下:
顺序:宏任务-微任务-渲染(如果需要渲染,比如到了时间,或有更改dom),而不是再次执行宏任务
微任务包含:1、“Promise”;2、“Object.observe”;3、“MutationObserver”;4、Node.js环境下的“process.nextTick”;5、“async/await”。
// 微任务
script(整体代码)
setTimeout
setInterval
I/O
UI交互事件
postMessage
MessageChannel
setImmediate(Node.js 环境)
// 宏任务
Promise
Object.observe
MutationObserver
process.nextTick(Node.js 环境)
async/await
console.log(1);
setTimeout(() => {
console.log(2);
});
console.log(3);
Promise.resolve(4).then(b => {
console.log(b);
});
console.log(5);
// => 13542
// 先执行同步代码,输出135
// 在执行微任务Promise,输出4
// 再执行宏任务setTimeout,输出2
// js代码执行流程,先执行同步代码,再清空(执行)微任务.then,最后是宏任务。
console.log(1);
setTimeout(() => console.log(2));
Promise.resolve().then(() => console.log(3));
Promise.resolve().then(() => setTimeout(() => console.log(4)));
Promise.resolve().then(() => console.log(5));
setTimeout(() => console.log(6));
console.log(7);
// => 1 7 3 5 2 6 4
// 立即输出数字 1 和 7,因为简单的 console.log 调用没有使用任何队列。
// 然后,主代码流程执行完成后,开始执行微任务队列。
// 其中有命令行:console.log(3); setTimeout(...4); console.log(5)。
// 输出数字 3 和 5,setTimeout(() => console.log(4)) 将 console.log(4) 调用添加到了宏任务队列的尾部。
// 现在宏任务队列中有:console.log(2); console.log(6); console.log(4)。
// 当微任务队列为空后,开始执行宏任务队列。并输出 2、6 和 4。