JavaScript高级面试题

typeof 和 instanceof 区别

typoef操作符返回一个字符串,表示未经计算的操作数的类型

instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上

区别:

typoef会返回一个变量的基本类型,instanceof返回的是一个布尔值

instanceof可以准确的判断复杂引用数据类型,但是不能正确判断基础数据类型

而typeof也存在弊端,他虽然可以判断基础数据类型,但是引用数据类型中,处了function类型以外,其他的也无法判断

js 使用 typeof 能得到的哪些类型?

typeof 只能区分值类型

typeof undefined // undefined

typeof null // object

typeof console.log // function

typeof NaN // number

解释一下什么是回调函数,并提供一个简单的例子?

被作为实参传入另一个函数,并在该外部函数内部被调用,用以来完成某些任务的函数,称为回调函数

什么是闭包?

一个作用域可以访问另一个函数内部的局部变量,或者说一个函数访问另一个函数中的变量,此时就会有闭包产生,那么这个变量所在的函数我们称之为闭包函数

什么是内存泄漏

内存泄漏是指:内存泄漏也称为‘存储渗漏’,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据内存单元。直到程序结束

哪些操作会造成内存泄漏?

1、垃圾回收器定期扫描对象,并计算了每个对象的其他的数量。如果一个对象的引用数量为0,或对该对象的唯一引用是循环的,那么该对象的内存即可回收

2、setTimeout的第一个参数使用字符串而非函数的话,会引发内存泄漏

3、闭包、控制台日志、循环

JS 内存泄漏的解决方式

常见的内存泄漏原因及解决方法_鹿指为码的博客-CSDN博客

说说你对原型(prototype)理解

JavaScript 中所有都是对象,在 JavaScript 中,原型也是一个对象,通过原型可以实现对象

的属性继承,JavaScript 的函数对象中都包含了一个” prototype”内部属性,这个属性所对

应的就是该函数对象的原型

prototype

作为函数对象的内部属性,是不能被直接访问的。所以为了方便查看一个对

象的原型,Firefox 和 Chrome 内核的 JavaScript 引擎中提供了”proto“这个非标准的访问器

原型的主要作用就是为了实现继承与扩展对象

介绍原型链

原型链:每一个对象,都有__proto__指向自身的原型。而原型也是对象,也有自己的__proto__指向原型的原型,以此类推形成链式结构,称之为原型链

常见的 js 中的继承方法有哪些

一、原型链继承

二、构造函数继承

三、组合继承

四、原型式继承

五、寄生式继承

六、寄生组合式继承

介绍 this 各种情况

1、以函数形式调用时,this永远都是window

2、以方法的形式调用时,this是调用方法的对象

3、以构造函数的形式调用时,this是新创建的那个对象

4、使用call和apply调用时,this是指定的那个对象

5、箭头函数:箭头函数的this看外层是否有函数,如果有,外层函数的this就是内部箭头函数的this如果没有,就是window

6、特殊情况:通常意义上this指针指向为最后调用它的对象。这里需要注意的一点就是如果返回值是一个对象,那么this指向的就是拿个返回值的对象,如果返回值不是一个对象那么this还是指向函数的实例

数组中的 forEach 和 map 的区别?

相同点:

1、都是循环遍历数组中的一项

2、每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)

3、匿名函数中的this都是指向window

4、只能遍历数组

不同点:

1、map()会分配内存空间存储新数组并返回,forEach不会返回数据

2、forEach()允许callback更改原始数据的元素,map()返回新的数组,map()不会对空数组进行检测

for in 和 for of 的区别

1、推荐在循环对象属性的时候使用 for...in,在遍历数组的时候的时候使用 for...of

2、for...in 循环出的是 key,for...of 循环出的是 value

3、注意,for...of 是 ES6 新引入的特性。修复了 ES5 引入的 for...in 的不足

4、for...of 不能循环普通的对象,需要通过和 Object.keys()搭配使用

call 和 apply,bind 的区别

相同点:作用相同,都是动态修改this指向;都不会修改原先函数的this指向

不同点:

执行方式不同

传参方式不同

修改this的性质不同

EventLoop 事件循环机制

EventLoop 事件循环机制_Dark_programmer的博客-CSDN博客_事件循环机制

js 防抖和节流

函数防抖:将几次操作合并为一次操作进行。原理是维护一个定时器,规定在延迟时间后触发函数,只有最后一次操作能被触发

函数节流:使得一定时间内只触发一次函数。原理是通过判断是否达到一定时间来触发函数

new 操作符具体干了什么呢?

1、创建一个空对象

2、设置原型链

3、改变this指向

4、判断Func的返回值类型

用 JavaScript 实现冒泡排序。数据为 23、45、18、37、92、13、24

//升序算法
function sort(arr){
for (var i = 0; i <arr.length; i++) {
for (var j = 0; j <arr.length-i; j++) {
if(arr[j]>arr[j+1]) {
var c=arr[j];//交换两个变量的位置
arr[j]=arr[j+1];
arr[j+1]=c;
}
};
};
return arr.toString();
}
console.log(sort([23,45,18,37,92,13,24]));

用 js 实现随机选取 10–100 之间的 10 个数字,存入一个数组并排序

function randomNub(aArray, len, min, max) {
if (len >= (max - min)) {
return '超过' + min + '-' + max + '之间的个数范围' + (max - min - 1) + '个
的总数';
}
if (aArray.length >= len) {
aArray.sort(function(a, b) {
return a - b
});
return aArray;
}
var nowNub = parseInt(Math.random() * (max - min - 1)) + (min + 1);
for (var j = 0; j < aArray.length; j++) {
if (nowNub == aArray[j]) {
randomNub(aArray, len, min, max);
return;
}
}
aArray.push(nowNub);
randomNub(aArray, len, min, max);
return aArray;
}
var arr=[];
randomNub(arr,10,10,100);

已知数组 var stringArray = [“This”,“is”, “Baidu”,“Campus”],Alert 出”This is Baidu Campus”

var stringArray = ["This", "is", "Baidu", "Campus"]
alert(stringArray.join(""))

已知有字符串 foo=”get-element-by-id”,写一个 function 将其转化成驼峰表示法”getElementById”

function combo(msg){
var arr=msg.split("-");
for(var i=1;i<arr.length;i++){
arr[i]=arr[i].charAt(0).toUpperCase()+arr[i].substr(1,arr[i].length-1);
}
msg=arr.join("");
return msg;
}

有 这 样一个URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e,请写一段 JS

程序提取 URL 中的各个 GET 参数(参数名和参数个数不确定),将

其按key-value 形式返回到一个 json 结构中,如{a: "1", b: "2", c: "", d:"xxx",e: undefined}

function serilizeUrl(url) {
var urlObject = {};
if (/\?/.test(url)) {
var urlString = url.substring(url.indexOf("?") + 1);
var urlArray = urlString.split("&");
for (var i = 0, len = urlArray.length; i < len; i++) {
var urlItem = urlArray[i];
var item = urlItem.split("=");
urlObject[item[0]] = item[1];
}
return urlObject;
}
return null;
 }

输出今天的日期,以 YYYY-MM-DD 的方式,比如今天是 2014年 9 月 26 日,则输出 2014-09-26

var d = new Date();
// 获取年,getFullYear()返回 4 位的数字
var year = d.getFullYear();
// 获取月,月份比较特殊,0 是 1 月,11 是 12 月
var month = d.getMonth() + 1;
// 变成两位
month = month < 10 ? '0' + month : month;
// 获取日
var day = d.getDate();
day = day < 10 ? '0' + day : day;
alert(year + '-' + month + '-' + day);}

把两个数组合并,并删除第二个元素。

var array1 = ['a','b','c'];
var bArray = ['d','e','f'];
var cArray = array1.concat(bArray);
cArray.splice(1,1);

写一个 function,清除字符串前后的空格。(兼容所有浏览器)

//使用自带接口 trim(),考虑兼容性:
if (!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\s+/, "").replace(/\s+$/,"");
}
}
// test the function
var str = " \t\n test string ".trim();
alert(str == "test string"); // alerts "true"

截取字符串 abcdefg 的 efg

alert('abcdefg'.substring(4));

判断一个字符串中出现次数最多的字符,统计这个次数

var str = 'asdfssaaasasasasaa';
var json = {};
for (var i = 0; i < str.length; i++) {
if(!json[str.charAt(i)]){
json[str.charAt(i)] = 1;
}else{
json[str.charAt(i)]++;
}
};
var iMax = 0;
var iIndex = '';
for(var i in json){
if(json[i]>iMax){
iMax = json[i];
iIndex = i;
}
}
alert('出现次数最多的是:'+iIndex+'出现'+iMax+'次');

将数字 12345678 转化成 RMB 形式 如: 12,345,678

//思路:先将数字转为字符, str= str + '' ;
//利用反转函数,每三位字符加一个 ','最后一位不加; re()是自定义的反转函数,最后再反转回去!
for(var i = 1; i <= re(str).length; i++){
tmp += re(str)[i - 1];
if(i % 3 == 0 && i != re(str).length){
tmp += ',';
}
}

split()和 join()的区别?

split()是把一串字符(根据某个分隔符)分成若干个元素存放在一个数组里

即切割成数组的形式;

join() 是把数组中的字符串连成一个长串,可以大体上认为是 split()的逆操作

JavaScript 中如何对一个对象进行深度 clone?

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>深克隆</title>
  <script>
function clone(obj)
{
if(typeof obj==‘object‘)
{
if(obj instanceof Array)
{
var result=[];
for(var i=0;i<obj.length;i++)
{
result[i]=clone(obj[i]);
}
return result;
}
else
{
var result={};
for(var i in obj)
{
result[i]=clone(obj[i]);
}
return result;
}
}
else
{
return obj;
}
}
var obj1=[12, {a: 11, b: 22}, 5];
var obj2=clone(obj1);
obj2[1].a+=5;
console.log(obj1, obj2);
</script>
</head>
<body>
</body>
</html>

js 数组去重,能用几种方法实现

一、使用for循环去重

二、使用set对象去重

三、使用数组索引indexOf()方法循环去重

四、使用includes()方法搭配for循环去重

五、使用fifter()方法搭配indexOf()方法去重

六、数组对象去重

常用的js数组去重的方法_~前端菜鸟的博客-CSDN博客_js数组去重

谈谈你对 Javascript 垃圾回收机制的理解?

1、标记清除(mark and sweep)

这是 JavaScript 最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,

垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离

开环境”

垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被

环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了

2、引用计数(reference counting)

在低版本 IE 中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该

变量的时候这个值的引用次数就加 1,如果该变量的值变成了另外一个,则这个值得引用次数减

1.当这个值的引用次数变为 0 的时 候,说明没有变量在使用,这个值没法被访问了,因此可以

将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为 0 的值占用的空间

在 IE 中虽然 JavaScript 对象通过标记清除的方式进行垃圾回收,但 BOM 与 DOM 对象却是通过

引用计数回收垃圾的,也就是说只要涉及 BOM 及 DOM 就会出现循环引用问题

class 和普通构造函数有何区别?

Js 构造函数:
function MathHandle(x,y){
this.x=x
this.y=y
}
MathHandle.prototype.add=function(){
return this.x+this.y
}
var m =new MathHandle(1,2)
console.log(m.add())
class 基本语法:
class MathHandle{
constructor(x,y){
this.x = x
this.y = y
}
add(){
return this.x + this.y
}
}
const m = new MathHandle(1,2)
console.log(m.add())
语法糖:
在上述两段代码中分别加入如下代码,运行
console.log(typeof MathHandle) // 'function'
console.log(MathHandle.prototype.constructor === MathHandle) //true
console.log(m.__proto__ === MathHandle.prototype) //true
运行结果一致。我认为,class 是构造函数的语法糖
综上所述:
class 在语法上更加贴合面向对象的写法
class 实现继承更加易读、易理解
更易于写 java 等后端语言的使用
本质还是语法糖,使用 prototype

JS 里垃圾回收机制是什么,常用的是哪种,怎么处理的?

JS 的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内

存还存在着,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的

内存

JS 中最常见的垃圾回收方式是标记清除

工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其

标记为“离开环境”。标记“离开环境”的就回收内存

工作流程:

垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记

去掉环境中的变量以及被环境中的变量引用的变量的标记

再被加上标记的会被视为准备删除的变量

垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间

什么是进程、什么是线程、它们之间是什么关系

进程:是指系统正在运行的一个应用程序

线程:线程则是CPU调度最小能独立运行的执行单元,也是有限的系统资源

两者之间的关系:一个进程之间至少包含一个或者多个线程,进程有一个独立的运行空间,其中的线程共享此空间,也拥有此进程的全部资源,因此可以并发执行

什么是任务队列?

任务队列(task queue)主要分两种:

1、宏任务(macrotask):在新标准中叫 task

1.1)主要包括:script(整体代码),setTimeout,setInterval,setImmediate,I/O,ui rendering

2、微任务(microtask):在新标准中叫 jobs

2.1)主要包括:process.nextTick, Promise,MutationObserver(html5 新特性)

3、扩展:

3.1)同步任务:在主线程上,排队执行的任务,只有前一个任务执行完毕,才能执

行后一个任务

3.2)异步任务:不进入主线程,而进入“任务队列”的任务,只有“任务队列”

通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行

栈和队列的区别?

1、栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的

2、队列先进先出,栈先进后出

3、栈只允许在一端进行插入和删除,而队列允许在一端进行插入,在另一端进行删除

栈和堆的区别?

1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。 堆

区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由 OS 回收

2、堆(数据结构):堆可以被看成是一棵树,如:堆排序; 栈(数据结构):一种先进后

出的数据结构

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 24
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值