相关知识点
布尔值被认定为false的值
undefined、null、NaN、""、0、false
typeof:返回数据类型,用于区分数据类型
typeof();/typeof 123;
有六个值:number string Boolean object undefined function
引用值返回object,null返回object,NaN返回number,undefined返回字符串"undefined"
undefined == null 结果为true
undefined === null 结果为false
undefined == false 结果为false
较为正确的解释:https://www.cnblogs.com/daysme/p/6408682.html
1. Number,Boolean,String,Undefined这几种基本类型混合比较时,会将其转换成数字再进行比较
2. 基本类型与复合对象进行比较时,会先将复合对象转换成基本类型(依次调用valueOf与toString方法)再进行比较 (?没看懂)
3. undefined被当成基本类型,undefined转换成数字是NaN,因此undefined与除null之外的其它类型值进行比较时始终返回false(注意NaN==NaN返回false)
4. null被当成复合对象,由于null没有 valueOf 与 toString 方法,因此和 除了undefined 之外的其它类型值进行比较时始终返回false
二、call apply bind 的区别
都可以改变this的指向
call : 参数要一个一个的传递,立即执行
apply : 参数以数组形式传递,立即执行
bind 会将改变this后的函数传递回来,不立即执行,在执行的时候传递参数
四、
1.
console.log(v1);
console.log(foo);
var v1 = 100;
function foo() {
console.log(v1);
var v1 = 200;
console.log(v1);
}
foo();
console.log(v1);
// out :
// undefined
// function foo() {
// console.log(v1);
// var v1 = 200;
// console.log(v1);
// }
// undefined
// 200
// 100
let a = 10;
var b = 11
function fn() {
console.log(this.a, this.b)
}
fn();
let obj = {
a: 5,
say: function() {
console.log(this.a)
fn();
arguments[0]();
}
}
obj.say(fn);
// my answer:
// 10 11
// 5
// 10 11
// 10 11
// 正确答案 :
// undefined 11
// 5
// undefined 11
// undefined undefined
let
块级作用域 :代码只在代码块内有效。不能从外向内找。
相当于C语言的变量,没有传进函数就不能使用。
let解释 :https://blog.csdn.net/ccc82284/article/details/54288237
第一个fn执行时,因为变量a是用let声明的,没有传入函数,所以this.a找不到,输出undefined,而变量b是用var声明的,通过作用域链在GO中能找到,输出11
(this.a/window.a 都不能找到let声明的变量)
第二个fn执行时,相当于在全局执行,所以结果同上
arguments[0]() 解释 :
这里 arguments 是javascript的一个内置对象,是一个类数组,其存储的是函数的参数。
(就是长的比较像数组,但是欠缺一些数组的方法,可以用slice.call转换成数组)
也就是说,这里arguments[0]指代的就是你say函数的第一个参数:fn,所以arguments[0]()的意思就是:fn()
为何这里输出undefined呢?say里面用this,不应该指向obj么?
实际上,这个this.a就是arguments.a。为啥这里的this指向了arguments呢?
因为在Javascript里,数组只不过使用数字做属性名的方法,
也就是说:`arguments[0]();`的意思,和`arguments.0()`的意思差不多(当然这么写是不允许的),
你更可以这么理解:
arguments = {
0: fn, //也就是 functon() { console.log(this.a, this.b) }
1: 第二个参数, //没有
2: 第三个参数, //没有
...,
length: 1 //只有一个参数
}
因为arguments里没有a、b,所以输出undefined
参考 : 面试题之arguments[0]
setTimeout(()=>{
console.log('timeout');
},0);
new Promise((resolve) => {
console.log('a');
setTimeout(()=>{
console.log('c');
}, 0);
resolve();
console.log('b');
}).then(() =>{
console.log('promise');
}).catch(() =>{
console.log('error');
});
console.log('code');
// my answer
// a
// b
// code
// timeout
// c
// promise
// 正确答案
// a
// b
// code
// promise
// timeout
// c
任务队列并不是只有一个,不同的任务对应着不同的任务队列。宏观任务放入宏观任务队列,微观任务放入微观任务队列,这些任务队列在栈空的时候被调入的优先级是微观任务队列优于宏观任务队列,当微观任务队列都清空的时候才执行宏观任务队列中的任务。
宏任务包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
微任务包括:process.nextTick, Promises, Object.observe, MutationObserver,MessageChannel
参考 :JS事件循环机制(event loop)之宏任务/微任务
五、
protoytpe是函数的原型,Person的prototype为Object.prototype
constructor是构造函数,Person的构造函数为function Person(){}
__proto__访问prototype
七、六种继承模式
- 子类的原型是父类的实例
function Father(){
}
function Son(){
}
Son.prototype = new Father()
- 借用构造函数继承
function Father(){
}
function Son(){
Father.call(this)
}
- 原型链+借用构造函数的组合继承
function Father(){
}
function Son(){
Father.call(this)
}
Son.prototype = new Father()
Son.constructor = Son
- 父类原型和子类原型指向同一对象
function Father(){
}
function Son(){
Father.call(this)
}
Son.prototype = Father.prototype
Son.constructor = Son
- 借助原型基于已有的对象来创建对象
function Father(){
}
function Son(){
Father.call(this)
}
Son.prototype = Object.create(Father.prototype)
Son.constructor = Son
- ES6中class 的继承
// ES6 类继承
// 父级构造函数
class Phone{
// 构造方法
constructor(brand,price){
this.brand = brand;
this.price = price;
}
// 父类的成员属性
call(){
console.log("调用父类的方法")
}
}
// 子级构造函数
class SmartPhone extends Phone{
// 构造方法
constructor(brand,price,color,size){
super(brand,price);// super就是父类的constructor 相当于Phone.call(this,brand,price); // this 指向Smartphone
this.color = color;
this.size = size;
}
call(){
console.log("调用子类的方法")
}
}
// 实例化对象
const xiaomi = new SmartPhone('小米',2999,'白色','4.7inch');
console.log(xiaomi);
xiaomi.call(); // 调用子类的方法