前端面试系列(一)
var和let的区别
var
声明在函数中则作用域就是该函数,声明在函数外则作用于为全局,js引擎执行代码时会提升变量到顶部。
let
作用域为当前所处的代码块,没有变量提升故而要先声明后使用,且不允许在相同作用域中重复声明同一个变量。
实例1:作用域对比
1 | { |
实例2:let在for循环中的使用
1 | for (let i = 0; i < 5; i++) { |
实例3:常见面试题
1 | for (var i = 0; i < 10; i++) { |
1 | 10 |
1 | for (let i = 0; i < 10; i++) { |
1 | 0 |
实例4:for循环特点,()
中的是父作用域,{}
中是子作用域。
1 | for (let i = 0; i < 3; i++) { |
1 | love |
== 和 === 有什么区别
==
允许自动类型转换
===
不允许自动类型转换
this
- 在对象方法中,this指向调用它所在方法的对象。
- 在全局环境中,this指向全局对象。
- 在函数中,this指向函数的所有者。
- 在函数中,严格模式,this指向
undefined
。 - 在事件中,this指向接收事件的元素。
call()
和apply()
可以指定函数执行的上下文环境,即this绑定的对象,可以将this引用到任何对象。
以下实例均在浏览器环境中运行。
实例1:方法中的this指向调用该方法的对象。
1 | var person = { |
实例2:单独使用this,指向全局对象(严格模式也是)。
1 | console.log(this); |
实例3:函数中使用this,指向函数所有者,也就是全局对象。
1 | function func() { |
实例4:严格模式下,函数中使用this,指向undefined。
1 | ; |
实例5:事件中的this,指向接收事件的html元素。
1 | <button onclick="this.style.display='none'">点击我消失</button> |
实例6:对象方法中绑定,这里对象是函数的所有者。
1 | var person = { |
实例7:显式函数绑定
使用call
和apply
切换函数执行上下文环境(context),也就是指定this指向的对象。
1 | var person1 = { |
上面这个例子中调用person1.fullName()
方法,使用call()
指定了this指向的对象为person2
,故而取得了person2
中的firstName
和lastName
。
什么是构造函数
使用new
关键字调用的函数为构造函数,通常构造函数的函数名首字母大写。
构造函数的样子如下:
1 | function Person(name, gender, hobby) { |
这样就可以通过new
来调用,也就是通过new
构造函数传入参数并快速创建对象:
1 | var p1 = new Person('小明', '男', '足球'); |
这样就达到了代码复用。
确定一个函数是构造函数的方法是看是否使用new
调用了它。
构造函数执行过程
- 使用
new
调用后会创建一个新的内存空间分配给实例。 - 函数题内部的this指向该内存空间。
- 执行函数题内代码
- 默认返回this。
如何将基于回调的函数转换为基于Promise的函数
实例:将getData
回调函数转换为Promise
1 | // the function itself |
Promise
构造函数接受一个回调,该回调接收两个函数:resolve
和reject
。在回调内部,你可以执行耗时的任务,并根据结果调用resolve
或reject
。
NaN === NaN ?
结果:false
NaN
不===
于任何值
0.1 + 0.2 === 0.3 ?
结果:false
事实上:0.1 + 0.2 = 0.30000000000000004
原因:js中的数字以IEEE 754
的双精度标准存储。无法精确表示0.1和0.2,故而结果对不对就看运气。
解决方法:将浮点数转化为整数运算。
1 | 0.1 + 0.2 |
1 | (1 + 2) / 1e1 |
输出:
1 | 0.3 |
js中的原始数据类型是什么
Boolean
Number
String
什么是严格模式
1 | ; |
以下省略一千字。
以下代码的输出是什么
1 | function func() { |
输出:
1 | undefined |
原因:
js会在第二行的return
后面自动添加分号;
,将后面的{}
代码块视为作用域而不是对象定义。