前端面试准备二

常见JS面试题

第一题

// 作用域、this、变量提升
var a = 10;
function test(){
    a = 100;
    console.log(a); // 100
    console.log(this.a);// 10
    var a;
    console.log(a);// 100
} 
test();

在JS中定义的函数内部使用var进行变量的定义,该变量存在变量提升,即在函数内部,JS解释器执行代码顺序为:

function test(){
	var a;
    a = 100;
    console.log(a); // 100
    console.log(this.a);// 10
    console.log(a);// 100
} 
test();

所以第一、第三个console.log(a)打印出来的值为100;
而console.log(this.a),此时要想知道这个值打印出来的结果,就得搞清楚this的指向问题,在本题中,test()函数无调用者,所以此时的this指向window,所以该处打印结果应为10;

function test(){
   a=100;
   console.log(a);
   var a;
} 
test();
function test(){
   console.log(a);
   var a = 100;
} 
test();

前者打印出来的a值为100,而后者打印出来的结果为undefined。此时可能会有同学有疑问,不是var存在变量提升吗,为什么会出现undefined呢,var的变量提升只是将变量的定义声明放在了最顶部,此时JS解释器执行代码的顺序如下;

function test(){
	var a;
   	console.log(a);
   	a = 100;
} 
test();

第二题

// 自执行函数、作用域
(function(){
    var a=b=3;  // b = 3; var a = b;
})()
console.log(b); // 3
console.log(a); // 报错

代码中var a=b=3;的代码实际意思相当于: b = 3; var a = b;
其中b并没有使用var定义,故b属于全局变量,而a属于函数内部声明变量,所以在函数外部访问不了a,能访问b。

第三题

// 事件循环、单线程、异步、等待队列
for( var i = 0;i < 3; i++){
	setTimeout(function(){
		console.log(i);
	},0)
}

本题输出结果为三个3,执行顺序为for主线程–setTimeout异步(放到等待队列)–继续执行for主线程直到执行完毕–执行setTimeout(此时i的值为3),故打印三个3。
若想要输出0,1,2,代码应进行如下修改:

for( let i = 0;i < 3; i++){
	setTimeout(function(){
		console.log(i);
	},0)
}

此时将var换为let,此时的let定义的i存在块级作用域,var定义的i为全局作用域,所以在for循环进行时会将前一个i 的值给覆盖掉,而let定义的i因为其存在块级作用域则不存在这个问题,所以能输出0,1,2。

第四题

function fun(n){
	console.log(n); // 123
	var n = 456;
	console.log(n); // 456
}
var n = 123;
fun(n);

该题考察点依旧是变量提升、作用域,逻辑比较简单,认真理解前面的题之后本题应该不成问题。以此输出为123、456。

function fun(){
	console.log(fun);
	fun = 456;
	console.log(fun);
}
fun();
var fun = 123;

在这里插入图片描述

第五题

//预解析、作用域
var n = 123;
function f1(){
	console.log(n); 
}
function f2(){
	var n = 456;
	f1();
}
f2(); // 123 此时无调用者 window
console.log(n); // 123

第六题

var length = 100;
function f1(){
	console.log(this.length);
}
var obj = {
	x:10,
	f2: function(f1){
		f1(); // 100 无调用者 window 
		arguments[0](); // 2 arguments[0] == f1
	}
}
obj.f2(f1,1);

arguments为JS内置函数,包含函数的实参,其作用域为arguments对象,故输出为arguments.length === 2;

第七题

function f(){
	console.log(this.a);
}
var obj = {
	a:10,
	f:f
}
var f2 = obj.f;
var a = 'heelo';
f2(); // 无调用者, window this指向window   heelo
obj.f(); // 10 此时调用者为obj,故this指向obj

第八题

// apply call -->第一个参数作用改变this指向,后面的参数为函数实参
function f(s){
	console.log(this.a,s); // 2,3
	return this.a + s; // 5
}
var obj = {
	a:2
}
var f2 = function(){
	return f.apply(obj,arguments);
}
var b = f2(3);
console.log(b); //  5

此题目关键在于对于apply函数的理解,使用apply函数的时候,第一个参数作用是改变调用者的this指向,后面的数组参数则是传入调用者的实参;
那么有的同学可能会有疑惑,apply和call的区别在哪里呢,其实就在于它们所需要传入的参数不同:
apply(obj, arguments):apply接收的第一个参数用于改变调用者的this指向,接收的第二个参数则是数组形式存在([1,2,3])
call(obj,…arguments):call接收的第一个参数同样用于改变调用者的this指向,但call接收的后面的参数则是直接接收(call(obj,1,2,3);这就是call和apply的区别。
那么对于这道题,如果把apply改为call的话,如果要得到相同的结果,那么需要怎么更改呢?

// apply call -->第一个参数作用改变this指向,后面的参数为函数实参
function f(s){
	console.log(this.a,s); // 2,3
	return this.a + s; // 5
}
var obj = {
	a:2
}
var f2 = function(){
	return f.apply(obj,...arguments); // return f.apply(obj,arguments[0]);
}
var b = f2(3);
console.log(b); //  5

数组去重

// Set函数去重
var a = [1,2,2,2,5,5,7,7]
console.log( new Set(a));
// 两次循环去重
var a = [1,2,2,2,5,5,7,7]

function uni(a){
	 for(var i = 0;i<a.length;i++){
		for(var j = i + 1;j<a.length;j++){
			if(a[i] === a[j]){
				a.splice(j,1);
				j--;
			}
		}
	}
	return a;
}
console.log(uni(a));
// indexOf去重
var a = [1,2,2,2,5,5,7,7]
function uni(a){
	var arr = [];
	for(var i = 0;i < a.length; i++){
		if(arr.indexOf(a[i]) === -1){
			arr.push(a[i]);
		}
	}
	 return arr;
}
console.log(uni(a));
// includes去重
var a = [1,2,2,2,5,5,7,7]
function uni(a){
	var arr = [];
	for(var i = 0;i < a.length; i++){
		if(arr.includes(a[i]) === -1){
			arr.push(a[i]);
		}
	}
	 return arr;
}
console.log(uni(a));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

X-Adobe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值