电话:19337019688
关闭
您当前的位置:首页 > 职场资讯 > 前端面试秘籍

JavaScript面试题相关专题

来源:商丘人才网_商丘招聘网_商丘人才市场_豫商人才网招聘平台 时间:2021-05-31 作者:Admin 浏览量:

(1)什么是闭包: 闭包是指有权访问另外一个函数作用域中的变量的函数。 闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。闭包就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。当在一个函数内定义另外一个函数就会产生闭包。

(2)为什么要用: 匿名自执行函数:我们知道所有的变量,如果不加上 var 关键字,则默认的会添加到全 局对象的属性上去,这样的临时变量加入全局对象有很多坏处,比如:别的函数可能误 用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链 上遍历的)。除了每次使用变量都是用 var 关键字外,我们在实际情况下经常遇到这样一 种情况,即有的函数只需要执行一次,其内部变量无需维护,可以用闭包。 结果缓存:我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象, 每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函 数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如 果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部 的引用,从而函数内部的值可以得以保留。 封装:实现类和继承等。

(3)闭包形成的条件:

1.函数的嵌套

2.内部函数引用外部函数的局部变量,延长外部函数的变量生命周期

(4)闭包的应用:

1、模仿块级作用域。

2、保存外部函数的变量。

3、封装私有变量。闭包的两个场景,闭包的两大作用:保存/保护

(5)闭包的优点: 延长局部变量的生命周期,

(6)闭包的缺陷:

1.闭包的缺点就是常驻内存会增大内存使用量,并且使用不当容易造成内存泄漏

2.如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。

说一下类的创建和继承

(1)类的创建(es5):new 一个 function,在这个 function 的 prototype 里面增加属性和 方法。 下面来创建一个 Animal 类: // 定义一个动物类

function Animal (name) {

// 属性

this.name = name || 'Animal';

// 实例方法

this.sleep = function(){

console.log(this.name + '正在睡觉!');

}

}

// 原型方法

Animal.prototype.eat = function(food) {

console.log(this.name + '正在吃:' + food);

};

这样就生成了一个 Animal 类,实力化生成对象后,有方法和属性。

(2)类的继承——原型链继承 --原型链继承

function Cat(){ }

Cat.prototype = new Animal();

Cat.prototype.name = 'cat';

// Test Code

var cat = new Cat();

console.log(cat.name);

console.log(cat.eat('fish')); console.log(cat.sleep());

console.log(cat instanceof Animal); //true

console.log(cat instanceof Cat); //true

介绍:在这里我们可以看到 new 了一个空对象,这个空对象指向 Animal 并且 Cat.prototype 指向了这个空对象,这种就是基于原型链的继承。 特点:基于原型链,既是父类的实例,也是子类的实例 缺点:无法实现多继承

(3)构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给 子类(没用到原型)


function Cat(name){

Animal.call(this);

this.name = name || 'Tom';

}

// Test Code

var cat = new Cat();

console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false

console.log(cat instanceof Cat); // true

特点:可以实现多继承 缺点:只能继承父类实例的属性和方法,不能继承原型上的属性和方法。

(4)实例继承和拷贝继承 实例继承:为父类实例添加新特性,作为子类实例返回 拷贝继承:拷贝父类元素上的属性和方法 上述两个实用性不强,不一一举例。

(5)组合继承:相当于构造继承和原型链继承的组合体。通过调用父类构造,继承父 类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用

function Cat(name){

Animal.call(this);

this.name = name || 'Tom';

}

Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; // Test Code

var cat = new Cat();

console.log(cat.name);

console.log(cat.sleep());

console.log(cat instanceof Animal); // true

console.log(cat instanceof Cat); // true

特点:可以继承实例属性/方法,也可以继承原型属性性/方法 缺点:调用了两次父类构造函数,生成了两份实例

(6)寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的 构造的时候,就不会初始化两次实例方法/属性


function Cat(name){

Animal.call(this);

this.name = name || 'Tom';

}

(function(){

// 创建一个没有实例方法的类

var Super = function(){};

Super.prototype = Animal.prototype;

//将实例作为子类的原型

Cat.prototype = new Super();

})();

// Test Code

var cat = new Cat();

console.log(cat.name); console.log(cat.sleep());

console.log(cat instanceof Animal); // true

console.log(cat instanceof Cat); //true

说说前端中的事件流

HTML 中与 javascript 交互是通过事件驱动来实现的,例如鼠标点击事件 onclick、页面 的滚动事件 onscroll 等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。 想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。 什么是事件流:事件流描述的是从页面中接收事件的顺序,DOM2 级事件流包括下面几个 阶段。

事件捕获阶段

处于目标阶段

事件冒泡阶段

addEventListener:addEventListener 是 DOM2 级事件新增的指定事件处理程序的操作, 这个方法接收 3 个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最 后这个布尔值参数如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示 在冒泡阶段调用事件处理程序。 IE 只支持事件冒泡。


如何让事件先冒泡后捕获

在 DOM 标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果,对 于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓 执行,直到冒泡事件被捕获后再执行捕获之间。


说一下事件委托

事件委托指的是,不在事件的发生地(直接 dom)上设置监听函数,而是在其父 元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判 断事件发生元素 DOM 的类型,来做出不同的响应。


JS 的 new 操作符做了哪些事情

new 操作符新建了一个空对象,这个对象原型指向构造函数的 prototype,执行构造函数 后返回这个对象。


改变函数内部 this 指针的指向函数(bind,apply,call 的区别)

通过 apply 和 call 改变函数的 this 指向,他们两个函数的第一个参数都是一样的表示要 改变指向的那个对象,第二个参数,apply 是数组,而 call 则是 arg1,arg2…这种形式。通 过 bind 改变 this 作用域会返回一个新的函数,这个函数不会马上执行。


JS 拖拽功能的实现

首先是三个事件,分别是 mousedown,mousemove,mouseup 当鼠标点击按下的时候,需要一个 tag 标识此时已经按下,可以执行 mousemove 里面的 具体方法。 clientX,clientY 标识的是鼠标的坐标,分别标识横坐标和纵坐标,并且我们用 offsetX 和 offsetY 来表示元素的元素的初始坐标,移动的举例应该是: 鼠标移动时候的坐标-鼠标按下去时候的坐标。 也就是说定位信息为: 鼠标移动时候的坐标-鼠标按下去时候的坐标+元素初始情况下的 offetLeft. 还有一点也是原理性的东西,也就是拖拽的同时是绝对定位,我们改变的是绝对定位条 件下的 left 以及 top 等等值。 补充:也可以通过 html5 的拖放(Drag 和 drop)来实现


Ajax 解决浏览器缓存问题

在 ajax 发送请求前加上 anyAjaxObj.setRequestHeader(“If-Modified-Since”,“0”)。 在 ajax 发送请求前加上 anyAjaxObj.setRequestHeader(“Cache-Control”,“no-cache”)。 在 URL 后面加上一个随机数: “fresh=” + Math.random()。 在 URL 后面加上时间搓:“nowtime=” + new Date().getTime()。 如果是使用 jQuery,直接这样就可以了 $.ajaxSetup({cache:false})。这样页面的所有 ajax 都会执行这条语句就是不需要保存缓存记录。


JS 的节流和防抖

防抖:短时间内多次触发同一个事件,只执行最后一次,或者在开始时执行,中间不执行。比如公交车上车,要等待最后一个乘客上车


节流:是连续触发事件的过程中以一定时间间隔执行函数。节流会稀释你的执行频率,比如每间隔1秒钟,只会执行一次函数,无论这1秒钟内触发了多少次事件

参考回答: http://www.cnblogs.com/coco1s/p/5499469.html


JS 中的垃圾回收机制

1.JS具有自动垃圾收集的机制

2.JS的内存生命周期(变量的生命) 1.分配你所需要的空间 var a = 20 2.使用分配带的内存(读写) alert(a + 10)

3.不适用的时候,释放内存空间 a = null 3.JS的垃圾收集器每隔固定的时间就执行一次释放操作,通用的是通过标记清除的算法

4.在局部作用域中,垃圾回收器很容易做出判断并回收,全局比较难,因此应避免全局变量 标记清除算法:js最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将他标记为’进入环境’, 当变量离开(函数执行完后),就其标记为’离开环境’。垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记, 然后去掉环境中的变量以及被环境中该变量所引用的变量(闭包)。在这些完成之后仍存在标记的就是要删除的变量了


如何理解前端模块化

前端模块化就是复杂的文件编程一个一个独立的模块,比如 JS 文件等等,分成独立的 模块有利于重用(复用性)和维护(版本迭代),这样会引来模块之间相互依赖的问题, 所以有了 commonJS 规范,AMD,CMD 规范等等,以及用于 JS 打包(编译等处理)的 工具 webpack。

对象深度克隆的简单实现

function deepClone(obj){

var newObj= obj

instanceof Array ? []:{};

for(var item in obj){

var temple= typeof obj[item] == 'object' ? deepClone(obj[item]):obj[item];

newObj[item] = temple;

}

return newObj;

}

ES5 的常用的对象克隆的一种方式。注意数组是对象,但是跟对象又有一定区别,所以 我们一开始判断了一些类型,决定 newObj 是对象还是数组。


==和===、以及 Object.is 的区别

(1)==主要存在:强制转换成 number,null==undefined==0 //true

“0==0 //true

!=“0” //true

123==123” //true

null==undefined //true

(2)Object.js 主要的区别就是+0!=-0 而 NaN==NaN (相对比===和==的改进)


自己实现一个 bind 函数

原理:通过 apply 或者 call 方法来实现。

(1)初始版本


Function.prototype.bind=function(obj,arg){

var arg=Array.prototype.slice.call(arguments,1);

var context=this;

return function(newArg){

arg=arg.concat(Array.prototype.slice.call(newArg));

return context.apply(obj,arg);

}

}


(2) 考虑到原型链 为什么要考虑?因为在 new 一个 bind 过生成的新函数的时候,必须的条件是要继承原 函数的原型


Function.prototype.bind=function(obj,arg){

var arg=Array.prototype.slice.call(arguments,1);

var context=this;

var bound=function(newArg){

arg=arg.concat(Array.prototype.slice.call(newArg));

return context.apply(obj,arg);

}

var F=function(){} //这里需要一个寄生组合继承

F.prototype=context.prototype; bound.prototype=new F();

return bound;

}


列举 I E 与 finefox 的不 同之处 :

不同之处如下 。

( 1 ) IE 支持 currentStyle; Firefox 使用 getComputStyle 。

( 2) IE 千史用 innerText· Firefox 千史用 textContent 。

( 3 )在透明度滤镜方面, IE 使用自lter:alpha(opacity= num); Firefox 使用-moz-opacity:

num 。

( 4 )在 事件方面, IE 使用 attachEvent: Firefox 使用 addEventListener 。

( 5 )对于鼠标位直: IE 使用 event.clientX; Firefox 使用 event.pageX 。

( 6) IE 千史用 event.srcElement· Firefox 千史用 event . target 。

( 7) 要消除 list 的原点, IE 中仅须使 margin:0 即可达到最终效果; Firetox 中需要设直margin:0 、padding:0 和 list” style:none 。

( 8 ) css 圆角: IE7 以下不支持圆角。


讲解一 下 JavaScript 对象的几种创建方式:

有以下创建方式:

( 1 ) Object 构造函数式 。

( 2 )对象字面量式 。

( 3 )工厂模式 。

( 4 )安全工厂模式 。

( 5 )构造函数模式 。

( 6 )原型模式 。

( 7) 混合构造函数和原型模式 。

( 8 )动态原型模式 。

( 9 )寄生构造函数模式 。

( 10 )稳妥构造函数模式 。


如何实现异步编程?

具体方法如下 。

方法 l ,通过回调函数 。 优点是简单、容易理解和部署 · 缺点是不利 于代码的阅读和维护,各个部分之间高度相合( Coupling ),流程混乱,而且每个任务只能指定一个回调函数。

方法 2 ,通过事件监听 。 可以绑定多个事件,每个事件可以指定多个回调函数,而且可以“去搞合”( Decoupling ),有利于实现模块化;缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰 。

方法 3 ,采用发布/订阅方式 。 性质 与“事件监听 ”类似, 但是明显优于后者 。

方法 4,通过 Promise 对象实现 。 Promise 对象是 CommonJS 工作组提出的 一种规范,旨在为异步编程提供统一接口 。 它的思想是,每一个异步任务返回一个 Promise 对象,该对象有 一个 then 方法,九许指定回调函数 。


JavaScript 中如何使用事件处理程序?

事件是 由用户与页面的 交 互(例如羊击链接或填写 表单) 导致的操作 。 需要一个事件处理程序来保证所有事件的 正确执行 。 事件处理程序是对象的额外属性 。 此属性包括事件的名称和事件发生时采取的操作 。


31. :.. :在 JavaSc 「ipt 中有-个函数,执行直接对象查找时,它始终不会查找

原型,这个函数是什么?

马: hasOwnPrope句 。

32. :. :在 JavaSc 「ipt 中如何使用 DOM?

品; DOM 代表文档对象模型,并且负责文档中各种对象的相王文互 。 DOM 是开发

网页所必需的,其中包括诸如段落、链接等对象 。 可以操作这些对象,如添加或删除

等 。 为此 , DOM 还需要向网页添加额外的功能 。

33. .::. : documen.wn怡和 inne 「HTML 的区别是什么?

品: document.write 重绘整个页面; innerHTML 可以重绘页面的一部分 。

34. .::. :在 JavaSc 「ipt 中读取文件的方法是什么?

品:可以通过如下方式读取服务器中的文件内容 。

function read.P.jaxFile (url) {

//创建 xhr

var xhr = new XMLHttpRequest() ;

//监听状态

xhr . onreadysta techange = function () {

//监听状态值是 4

if (xhr . readyState === 4 晶晶 xhr.status === 200) {

console . log(xhr . responseText)

//打开请求

xhr . open ( ’ GET ', url , true)

//发送数据

xhr . send(null)

可以通过如下方式读取本地计算机中的内容 。

function readinputFile (id) {

var file= document . getElementByid(id) . files[O] ;

//实例化 FileReader

var reader= new FileReader ();

//读取文件

reader . readAsText(file)

//监听返回

reader . on load = function (data) {

console . log(data , this . result)

35. 4:如何分配对象属性?

马:将属性分配给对象的方式与赋值给变量的方式相同。例如,表羊对象的操作值

以下列方式分配给”submit”: document.form.action =”submit” 。

36. .::.:请说几条书写 JavaScript 语句的基本规范 。

由 :基本规范如下 。

( 1 )不要在同 一行声 明多个变量 。

( 2 )应使用===/!==来比较 true/false 或者数值 。

( 3 )使用对象字面量替代 new Array 这种形式 。

( 4 )不要使用全局函数。

( 5 ) switch 语句必须带有 defau lt 分支 。

( 6 )函数不应该有时有返回值,有时没有返回值 。

( 7 ) for 循环必须使用大括号括起来 。

( 8 ) i f 语句必须使用大括号括起来 。

( 9 ) for-in 循环中的变量应该使用 var 关键字明确限定的作用域,从而避免作用域污染 。

37. .:.. : eval 的功能是什么?

品: 它的功能是把对应的字符串解析成 JavaScript 代码并运行 。

应该避免使用 eval ,它会造成程序不安全,非常影响性能(执行两次, 一次解析成

JavaScript 语句, 一 次执行) 。

38. .:.: [「”,??,”3"] . map(parselnt)的执行结果是多少?

品:[ 1, NaN, NaN] ,因为 parselnt 需要两个参数( val, radix ), 其中 radix 表示解析时用的

基数(进制); map 传递了 3 个参数( item, index, array ),对应的 radix 不合法导致解析失败。

39. .:.:谈谈你对 th i s 对象的理解 。

.7.: this 是 JavaScript 的一个 关键字,随着函数使用场合的 不同 , this 的值会发生变

化 。 但是有 一个总原则 , 即 this 指的是调用函数的那个对象 。

一般情况下 , this 是全局对象 Global , 可以作为方法调用 。

40. .7..: web-ga 「den 和 web-farm 有什么不同?

品: web-garden 和 web-farm 都是网络托管系统 。 唯一的区别是 web-garden 是在单个

服务器中包含许多处理器的设直,而 web”farm 是使用多个服务器的较大设置 。

41. A:说一下 document.write()的用法 。

品: docume旺 write()方法可以用在两个地方 ,页面载入过程中用实时脚本创 建 页面

内容,以及用延时脚本创建本窗口或新窗口的内容 。

document.wr ite 只能重给整个页面, innerHTML 可以重给页面的一部分 。

42. :.. :在 Java Sc 「ipt 中什么是类 (伪) 数组?如何将类 (伪) 数组转化为标

准数组?

品: 典型的类(伪)数组是函数的 argument 参数, 在调用 getElementsByTagName

和 docum ent.childNodes 方法时 ,它们返回的 NodeList 对 象都属 于伪数组。可以使用

Array.prototype.slice.call ( fakeArray )将数组转化为真正的 Array 对象 。

43. :., : JavaSc「ipt 中 ca ll ee 和 ca ll凹的作用是什么?

品: caller 返回 一个关于函数的引用,该函数调用了当前函数; callee 返回正在执行

的函数,也就是指定的 function 对象的 正文 。

44. .:.:讲一下手写数组快速排序的步骤 。

品:“快速排序”的思想很简单,整个排序过程只需要 3 步 。

( 1 )在数据 集之中,选择一个元素作为“基准”( pivot ) 。

( 2 )将所有小于 “基准 ”的元素,都移 到 “基准 ”的左边; 将所有大于 “基准”的

元素,都移到“基准”的右边 。

( 3 )对“基准”左边和右边的两个子集 , 不断重复第( 1 )步和第( 2 )步 , 直到所

有子集只剩下一个元素 为止 。

45. .::. :如何统计字符串飞aaabbbccccddfgh ”中字母的个数或统计最多的

字母数?

品: 具体代码如下 。

var str = ” aaaabbbccccddfgh ”;

function dealStr (str) {

var obj = {) ;

for (var i = 0 ; i < str. l ength; i++ ) {

var v = str . charAt {i );

if (obj[v] && ob][v) .value===v) {

++ob][ v] . count

) else {

obj[v] = {

count : 1 ,

value : v

retu r n obj ;

var ob]= dealStr (str) ;

for (key in obj) {

console . log(obj[key) . value + ’ = ’ + obj [key] . count)

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

马: 具体代码如下 。

function trim(str) {

if (str && typeof str ===”s tring”){

return str . replace ( 尸\ s+ l \s +♀/ g , ”” ) ; //去除前后空白符

47. .::. :歹lj 出不同浏览器中关于 JavaScript 兼容性的两个常见问题 。

马:( 1 )事件绑定兼容性问题 。

IE8 以下的浏览器不支持用 addEventListener 来绑定事件 ,使用 attach event 可以 解 决

这个问题 。

( 2 ) stopPropagation 兼容性问 题。


微信扫一扫分享资讯
下一篇: 说说&和&&的区别
微信公众号
手机浏览

Copyright © 2022 All Rights Reserved 版权所有 豫商人才网 豫ICP备19004769号

地址:河南省商丘市睢阳区神火大道176号联合大厦13楼 EMAIL:postmaster@37jobs.com

用微信扫一扫