1、运算符
- 问题:
○ 下面代码中,a在什么情况下,会执行输出语句打印1? - 代码:
var a= ?
if(a==1 && a==2 && a==3){
console.log(1)
}
- 解决:
- 3-1、利用
toString()
方法
- 3-1、利用
// 1、将a赋值为一个对象
var a = {
// 2、定义对象a中的属性i为1
i: 1,
// 3、在if条件中比较数值时,覆盖会调用的`toString()`方法,直接返回对象a中i值++,因为是后置++,所以初始值还是1,则在进行`a==1`比较时,可以通过
// 1)后续每次`if比较`时,都会调用到`toString()`方法,继续进行`i++`操作
// 2)调用`toString()方法`是因为在比较值时,`js`会自动调用该方法
// 3)完整的比较顺序应该是:
// A. 和数值进行对比时:需要用到`Number()`转换类型,但是转换之前会先用到`valueOf()`尝试转换
// B. 如果返回的还是对象,则调用`toString()`,当前在`toString()`这里直接改写了,所以就将数据直接返回了
toString() {
return a.i++;
}
}
// 4、使用 if 条件语句进行比较
// 1)在第一次比较时,调用 a.toString(),a.i++ 返回 1,因此 a == 1 为 true
// 2)在第二次比较时,再次调用 a.toString(),a.i++ 返回 2,因此 a == 2 为 true
// 3)在第三次比较时,继续调用 a.toString(),a.i++ 返回 3,因此 a == 3 为 true
// 4)因为三个比较都为 true,因此执行 console.log(1)
if (a == 1 && a == 2 && a == 3) {console.log(1);}
- 3-2、利用
valueOf()
方法
var a = {
i: 1,
// 将上面的toString()换成valueOf()即可
valueOf() {
return a.i++;
}
}
if (a == 1 && a == 2 && a == 3) {console.log(1);}
2、原型和原型链
2.1、谈谈对Js中原型与原型链的理解?
- 每个
对象
都有一个_proto_ 属性
,该属性指向自己的原型对象 - 每个
构造函数
都有一个prototype属性
,该属性指向实例对象的原型对象 - 原型对象里的
constructor
指向构造函数本身 - 实例对象的
constructor属性
是从它的原型对象上访问到的
2.2、对一个构造函数实例化后,它的原型链指向什么?
- 指向该构造函数实例化出来对象的原型对象
- 对于构造函数来讲,可以通过
prototype
访问到该对象 - 对于实例对象来讲,可以通过
隐式属性_proto_
来访问到
3、谈谈对JS中的执行上下文的理解
- 概念:
a. 简单概括为:代码(全局/函数代码)执行前进行的准备工作
b. 如:确定作用域、创建局部变量对象,也称为“执行上下文环境” - 执行上下文类型有:
a. 全局执行上下文
b. 函数执行上下文:在调用时产生 - 注意:
执行上下文的
生命周期
有两个阶段,执行阶段只是上下文生命周期中的第二步:
○创建阶段(进入执行上下文)
:函数被调用时,进入函数环境,为其创建一个执行上下文
○执行阶段(代码执行)
:执行函数中代码时,此时执行上下文进入执行阶段。
4、谈谈对JS中的执行栈的理解
- 执行栈遵循
“先进后出,后进先出”
的规则,出口在栈的顶部,且只有一个 - 执行栈的主要功能是:管理和追踪代码执行的顺序
5、谈谈对JS中的作用域的理解
- 概念:
a. 作用域就是一个独立的地盘,让变量、函数等不会外泄、暴露出去。
b. 也就是说:作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。 - 分类:
a.全局作用域
:在代码中任何地方都能访问到的对象拥有全局作用域
b.函数作用域
:是指变量在函数内部声明时,该变量只能在该函数内部访问
c.块级作用域
:是指变量在块(由{}包围的代码块内部)声明时,该变量只能在该块内部访问。
6、谈谈对JS中的作用域链的理解
- 概念:
a.作用域链
是指:在嵌套的函数中,变量和函数的查找过程。
b. 每个函数都有自己的作用域,但,可以访问外层函数和全局作用域中的变量。 - 详解:
○全局作用域
:最外层,所有代码都能访问。
○函数作用域
:每个函数都有自己的作用域,内部函数可以访问外部函数和全局作用域中的变量
○作用域链的形成
:当代码执行时,如果在当前作用域找不到某个变量,就会沿着作用域链向上查找,直到找到或到达全局作用域
7、this指向
- 在函数体中,非
显式/隐式
地简单调用函数时:
a. 在严格模式
下:函数内的this会被绑定到undefined
上
b. 在非严格模式
下:则会被绑定到全局对象window/global
上 - 一般使用new方法调用构造函数时,构造函数内的this会被绑定到新创建的对象(实例对象)上
- 一般通过call/apply/bind方法显式调用函数时,函数体内的this会被绑定到指定参数的对象上
- 一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上
- 在箭头函数中,this的指向是由外层(函数或全局)作用域来决定的
8、闭包
8.1、闭包是什么?
闭包
不是一个具体的技术,而是一种现象,是指:在定义函数时,周围环境中的信息可以在函数中使用- 换句话说:执行函数时,只要在函数中使用了外部的数据,就创建了闭包,作用域链,则是实现闭包的手段
8.2、闭包的应用场景有哪些?
- 作用域空间不销毁
- 可以在函数外部访问函数内部的变量,也就是:在全局访问局部变量
- 保护私有变量:在外部函数声明,在内部函数引用的变量
8.3、怎么销毁闭包?
- 如果是自动产生的闭包,我们无需操心闭包的销毁,会自动销毁
- 如果是手动创建的闭包:
a. 可以把被引用的变量设置为null
,即:手动清除变量
b.Js垃圾回收器
在进行垃圾回收时,发现此变量已经没有任何引用,就会把设为null
的变量给回收了
9、谈谈事件委托以及冒泡原理
9.1、事件委托
- 事件委托是利用事件冒泡原理,把事件处理器绑定到一个父元素上,而不是每个子元素都绑定事件处理器。
- 这样做可以:提高性能,减少内存消耗,并且可以处理动态添加的子元素
9.2、冒泡原理
- 冒泡原理是指事件在
DOM树
中从目标元素开始向上层元素传播的过程。 - 事件首先触发目标元素上的处理函数,然后逐级向上传播至
根元素
10、如何阻止默认事件
所谓默认行为,一般是指HTML元素所自带的行为,如:点击一个a元素时会跳转
event.preventDefault()
event.returnValue = false
○ 该特性已经从web标准中删除,虽然一些浏览器目前还支持它,但尽量不要使用该特性return false
○ 不建议滥用,同时:jQuery
中可以同时阻止冒泡和默认事件