(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