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 内存泄漏的解决方式
说说你对原型(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、堆(数据结构):堆可以被看成是一棵树,如:堆排序; 栈(数据结构):一种先进后
出的数据结构