js面试题

一、作用域

1、写出console.log结果(作用域)

(function(){
	var a = b = 2;
})()
console.log(typeof a==='undefined'); //true
console.log(typeof b==='undefined'); //false

考查点:作用域

解析
var a = b = 2;
相当于
b = 2;//b没有var修饰符,相当于全局变量
var a = b;//a是函数内变量,函数外访问不了,直接访问a,会报引用错误(ReferenceError)

2、写出console.log结果(作用域和变量提升)

var name = 'World!';
(function(){
	if(typeof name == 'undefined'){
		var name = 'Lucy';
		console.log("Goodbye "+name);//Goodbye Lucy
	}else{
		console.log("Hi "+name);
	}
})()
输出结果:Goodbye Lucy

考查点:作用域和变量提升

解析
Js代码分为两个阶段:预编译阶段(预处理)和执行阶段,在编译阶段找到所有声明(包括var声明和函数声明),将声明提升至作用域的顶部。

(function(){
	if(typeof name == 'undefined'){
		var name = 'Lucy'; // var变量声明同时赋值
		console.log("Goodbye "+name);//Goodbye Lucy
	}else{
		console.log("Hi "+name);
	}
})()
相当于:
(function(){
	var name; //var变量提升
	if(typeof name == 'undefined'){
		name = 'Lucy'; //仅赋值
		console.log("Goodbye "+name);//Goodbye Lucy
	}else{
		console.log("Hi "+name);
	}
})()

3、写出console.log结果(变量提升、函数提升,调用顺序)

var a = 1;  
function a(a) {  
    console.log(a);  
    var a = 3;  
}  
a(6);  //Uncaught TypeError: a is not a function

考查点

  1. 变量和函数声明提升:js包含预处理和执行阶段;在预处理期 对变量和函数进行处理,将变量和函数声明提升至作用域的顶部。
  2. 调用顺序:预处理时,先变量后函数,当变量名和函数名一致时,后者会覆盖前者。

解析
这里我们详细解析下输出结果:预处理期,先处理var a,然后处理函数a,此时typeof a为function;代码执行阶段,对a进行赋值,此时a=1,则a的类型为number,所以a(6)会报错。

示例:变量提升

var a = 2    
function fn() {    
    console.log(a)    
    var a = 3    
}  
fn()  //undefined
函数fn内,var a提升在作用域顶部,相当于
function fn(){
	var a;
	console.log(a);
	a = 3;
}

示例:先变量后函数,函数声明覆盖变量声明

function b(){
}
var b;
console.log(typeof b);//function

4、写出输出结果:作用域问题

var arr=[];
for(var i=0;i<10;i++){
	arr.push(function(){console.log(i)});
}
//代码1
arr[1]();//10;
//代码2
for(var i=0;i<10;i++){
	arr[i](); //0,1,2,3,4,5,6,7,8,9
}

结果解析:
代码1输出解析:代码1输出结果为10,因为此时调用方法,变量i值已经为10;所以调用arr中任何一个元素的方法都会返回10。
代码2输出解析:代码2输出结果为0,1,2,3,4,5,6,7,8,9,当执行for循环时,i变量的值发生了变化,所以在循环中立即调用数组arr中元素的方法时,返回的是当前i变量的值。

5、写出输出结果(考查作用域)

var obj = {
    color: "red",
    fun: function() {
        var self = this;
        console.log("out_fun:" + this.color);//"red"
        (function() {
            console.log("inner_fun:" + this.color);//undefined
            console.log("inner_fun:" + self.color);//"red"
        }());
    }
};
obj.fun();

考查点:考查作用域和闭包问题
结果解析:fun中IIFE(立即调用的函数表达式)有自己的作用域,其中的this指向window,window中没有color属性,所以this.color返回undefined;但是它能访问父层的作用域,所以self.color返回值是red。

6、考查作用域

自由变量跨作用域取值时,要取创建这个函数的作用域取值,而非父作用域。

var m = 10;
var fn = function(n){
	if(n > m){
		console.log(n);  //15
	}
};
(function(f){
	var m = 100;
	f(15);
})(fn)

ps: 所谓自由变量就是变量调用和声明的作用域不同。例在 fn函数中 用到变量 m,但并没有在 fn 中声明,要到别的作用域中找它,这个变量 m就是自由变量

7、考查闭包、作用域

变量取值:首先要在该函数内取值 -》如没有,再去创建这个函数的作用域取值,而非父作用域 -》如创建这个函数的作用域依然没有,继续往上查找,直到全局作用域;如果全局作用域也没找到,那么这个变量就不存在。
在这里插入图片描述

二、算法相关

1、找出两个字符串的不同

//利用正在exec方法
function fn(str1,str2){
    var re = new RegExp("[^"+str1+"]|[^"+str2+"]","g");
    var arr = [],tmp=null;
    while((tmp=re.exec(str1+str2))!=null){
        arr.push(tmp[0])
    }
    return arr;
}
fn("Hi,I am Lucy!","Hi,I'm Lily!"); //["a", "u", "c", "'", "l"]


//利用match方法
function fn2(str1,str2){
    var re = new RegExp("[^"+str1+"]|[^"+str2+"]","g");
    return (str1+str2).match(re);
}
fn2("Hi,I am Lucy!","Hi,I'm Lily!"); //["a", "u", "c", "'", "l"]

考查点:正则表达式
解析:exec可以返回更多的信息:正则匹配结果,匹配结果的索引值(index属性值),原数组(input属性值)

2、给定一个由N个整数组成的数组,数组中有正数也有负数,数组中一个或多个连续元素可以组成一个子数组,请从这些连续元素组成的子数组中找出和最大的子数组,并给出该子数组的起始元素和结尾元素的索引值

var  arr1=[1,-2,3,4,6,-10,12];
function getMaxSum(arr){
	if(!arr || !arr.length){
		return "数组为空";
	}
	var max = 0;
	var sum = 0;
	var start = 0;
	var oldStart = 0;
	var end = 0;
	for(var i=0,ln=arr.length;i<ln;i++){
		if(sum<=0){
			start = i;
			sum = 0;
		}
		sum += arr[i];
		if(sum>max){
			max = sum;
			end = i;
			if(end>=start){
				oldStart = start;
			}
		}
	}
	return {max:max,start:oldStart,end:end};
}
console.log(getMaxSum(arr1));//{"max":15,"start":2,"end":6}

3、给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

例如:字符串"abcabbcbbcca",的不含重复字符的最长子串为"abc",其长度为3.

function maxSubstringLen(str) {
    var newStr = "";
    var longStr = "";
    var strArr = str.split("");
    for(var i=0;i<strArr.length;i++){
    	if(newStr.indexOf(strArr[i])==-1){
    		newStr += strArr[i];
    	}else{
    		if(longStr.length<newStr.length){
				longStr = newStr;
			}
    		var index = newStr.indexOf(strArr[i]);
    		newStr = newStr.substring(index+1)+strArr[i];
    	}
    }
    if(longStr.length<newStr.length){
		longStr = newStr;
	}
    return longStr.length;
};

maxSubstringLen("abcabbcbbcca");//3

三、JS基础

1、使用 typeof 判断一个引用类型的值 是不是 对象的弊端,如何正确判断对象?

弊端:用typeof不能准确判断一个引用类型是object、array还是null。
解决方法:用Object.prototype.toString.call(待判断数据类型的元素)。

console.log(typeof [] === 'object' );//true
console.log(typeof null === 'object' );//true
console.log(typeof {} === 'object' );//true

//准备判断对象类型的方法:
Object.prototype.toString.call([]);//"[object Array]"
Object.prototype.toString.call(null);//"[object Null]"
Object.prototype.toString.call({});//"[object Object]"

2、map和parseInt

[1,2,3].map(parseInt); //[1, NaN, NaN]

该题同时考察map和parseInt的用法:
map: array.map(function(value,index,arr), thisParam)

参数描述
function(value,index,arr)必填
thisParam选填,改变函数中this指向

parseInt:parseInt(string, radix)

参数描述
string必填;要被解析的字符串。
radix选填;要解析的数字的基数,介于 2 ~ 36 之间。

3、new 创建实例的过程

实现步骤:
1)创建一个新对象;
2)新对象连接到构造函数原型上;
3)执行构造函数代码(将this指向obj,为这个新对象添加属性);
4)返回新对象。

实现代码:

function create(Fn) {
    if (typeof Fn !== 'function') {
        throw 'Fn must be a function';
    }

    // 1、创建一个对象新对象
    var obj = new Object()
    // 2、给该对象的__proto__赋值为Fn.prototype,即设置原型链
    obj.__proto__ = Fn.prototype
    // 3、执行Fn,并将obj作为内部this
    var ret = Fn.apply(obj, [].slice.call(arguments, 1));
    // 4、如果Fn有返回值,则将其作为new操作返回内容,否则返回obj
    return ret instanceof Object ? ret : obj;
};

4、内存泄漏

  • 意外的全部变量:局部作用域中未生命的变量;
  • setTimeout 的第一个参数使用字符串而非函数;
  • 闭包;
  • Dom引用:Dom元素被删除时,内存中的引用未被正确清空;
  • 控制台(console.log)

四、考查点

1、跨域问题
2、js设计模式(单例模式)
3、原型链
4、闭包
5、请求响应过程
6、浏览器垃圾回收机制
7、如何比较两个对象是否相等
8、防抖和节流
9、页面关闭监听
10、跨站脚本攻击(XSS)
11、页面计时中关闭再次打开,如何保证计时有效
12、如何实现浏览器内多个标签页之间的通信

原创内容,转载请标记出处:https://blog.csdn.net/yihanzhi/article/details/79664156

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值