前端常见JS问题总结
1. Call 和 Apply 的区别
语法:
function.call(thisObj [, arg1[, arg2[, [, ...argN]]]]);
function.apply(thisObj [, argArray] );
定义: call 和 apply 可以让我们⼿动设置 this 指向
两个参数:第⼀个参数是绑定 this 指向;第⼆个参数是向将要执⾏的函数传递的参数
区别:第⼆个参数, call 以⼀个⼀个的形式传递参数;apply 以数组的形式传递参数
var a = 10;
function sum(num1, num2) {
console.log(this.a + num1 + num2);
}
var obj = {
a: 20
}
sum(10, 10);    //30
sum.call(obj, 10, 10);      // 40
sum.apply(obj, [10, 10]);    // 40
js合并两个数组
2. 键盘事件属性
event.keyCode;    // 获取按下的键盘按键的键码值(Unicode值)
event.shiftKey;  // 获取是否按下了shift键
event.altKey;    // 获取是否按下了alt键
3. ⿏标事件属性
event.screenX/event.screenY    // 获取⿏标基于屏幕的X轴/Y轴坐标
event.clientX/event.clientY    // 获取⿏标基于浏览器窗⼝的X轴/Y轴坐标
event.pageX/event.pageY        // 获取⿏标基于⽂档的X轴/Y轴坐标
event.button  // 获取⿏标按下的键。⾮IE浏览器中0为⿏标左键,1为⿏标中键,2为⿏标右键
event.which    // 获取指定事件上哪个键盘键或⿏标按钮被按下
4. addEventListener 和 attachEvent 区别
attachEvent⽅法适⽤于IE
attachEvent中的事件带on,⽽addEventListener中的事件不带on
attachEvent ⽅法有两个参数:第⼀个参数为事件名称,第⼆个参数为接收事件处理的函数; addEventListener ⽅法有三个参数:第⼀个参数为事件名称(不含 on,如 "click"),第⼆个参数为要接收事件处理的函数,第三个参数为⼀个bool值,默认为false
  1. 添加多个事件处理程序执⾏的顺序不同
addEventListener:
var ElementById("myBtn");
btn.addEventListener("click",function(){
alert(1);
},false);
btn.addEventListener("click",function(){
alert(2);
},false);
//执⾏结果 1 ,2
attachEvent:
var ElementById("myBtn");
btn.attachEvent("onclick",function(){
alert(1);
});
btn.attachEvent("onclick",function(){
alert(2);
});
//执⾏结果 2 ,1
  2. 事件处理程序的作⽤域不同
DOM2级事件添加的事件处理程序,它的作⽤域是所属的元素,⽽IE的事件处理程序会在全局作⽤域中运⾏。addEventListener:
var ElementById("myBtn");
btn.addEventListener("click",function(){
console.log(this.id);    // myBtn
},false);
attachEvent:
var ElementById("myBtn");
btn.attachEvent("onclick",function(){
alert(this===window);    // true
});
  3. 移除绑定事件 removeEventListener() 和 detachEvent()
移除 addEventListener 事件:
event: 事件名,注意不使⽤“on”前缀,如 click
function: 指定事件触发时执⾏的函数
useCapture: 指定事件是否在捕获或冒泡阶段执⾏
true: 在捕获阶段执⾏
false: 在冒泡阶段进⾏,默认值为false
如果添加时⽤的捕获阶段,那么在移除时也要⽤捕获阶段,否则⽆法移除它们
如果是同⼀个元素同⼀个调⽤函数同⼀个useCapture值绑定多次,在移除时只需要执⾏⼀次移除
移除 attachEvent 事件:
element.detachEvent(event, function)
event: 事件名,注意要使⽤“on”前缀,如 onclick
function: 指定事件触发时执⾏的函数
5. addEventListener 和 on 区别
<div id="box">addEventListener 和 on 区别</div>
var box = ElementById("box");
console.log("我是box1");
}
console.log("我是box2");
}
}
//运⾏结果:“我是box2”
var box = ElementById("box");
box.addEventListener("click", function(){
console.log("我是box1");
})
box.addEventListener("click", function(){
console.log("我是box2");
})
}
运⾏结果:我是box1
     我是box2
第⼆个onclick会把第⼀个onclick给覆盖了,虽然⼤部分情况我们⽤on就可以完成我们想要的结果,但是有时我们⼜需要执⾏多个相同的事件,很明显如果⽤on完成不了我们想要的,⽽addEventListener可以多次绑定同⼀个事件并且不会覆盖上⼀个事件。
6. HTML5 新增的事件
contextmenu事件
这个事件是当⿏标右击的时候触发的,但是触发这个属性的时候默认的⾏为也会被触发,所以需要通过preventDefault()⽅法来阻⽌。
beforeunload事件
beforeunload在页⾯卸载之前触发,该事件会弹出⼀个对话框,询问是否确定离开。
hashchange事件
该事件当URL中的hash值改变时触发,通常⽤于Ajax应⽤中利⽤URL参数保存导航信息;这个在前端路由的制作中是⾮常有⽤得。
7. 阻⽌事件默认⾏为和阻⽌事件冒泡
<div id="wrap" >
<div id="btn" ></div>
<a id="prevent" target="_blank" href="www.baidu">preventDefault</a>
</div>
标准浏览器的使⽤⽅法
preventDefault(): ⽤于阻⽌事件的默认⾏为;
⽐如: a 链接的跳转⾏为和表单⾃动提交⾏为 
var prevent = ElementById("prevent");
prevent.addEventListener("click", function(event){
event.preventDefault();
}, false);
//使⽤preventDefault()⽅法就阻⽌了a标签打开新窗⼝的默认⾏为
stopPropagation(): ⽤于阻⽌事件的进⼀步获取和传播;
⽐如:阻⽌事件继续向上层冒泡
var btn = ElementById("btn"),
wrap= ElementById("wrap");
btn.addEventListener("click",function(event){
alert("btn");
event.stopPropagation();
},false);
wrap.addEventListener("click",function(){
alert("wrap");
},false);
//点击btn时,这样就阻⽌了id="btn"向上级id="wrap"冒泡,打印出来的结果是:弹窗仅弹出btn。否则,将会先弹出btn,然后弹出wrap。
低版本IE浏览器的使⽤⽅法
event.cancelBubble = true;  //阻⽌事件的进⼀步获取或者冒泡;
⽰例
function prevent(event) {
event = event || window.event;
if(event.preventDefault) {
event.preventDefault();
} else {
}
}
//使⽤ if else 去判断
8. 事件捕获和事件冒泡
事件冒泡执⾏过程:从最具体的的元素(你单击的那个元素)开始向上开始冒泡,下⾯的案例的顺序是:content > wrap 事件捕获执⾏过程:从最不具体的元素(最外⾯的那个盒⼦)开始向⾥⾯冒泡,下⾯的案例的顺序是:wrap > content
<div id="wrap">
<div id="content"></div>
</div>
(addEventListener第三个参数写的是false,默认为false)
var wrap= ElementById("wrap");
var content= ElementById("content");
wrap.addEventListener("click", function(){
console.log("我是wrap");
}, false)
content.addEventListener("click", function(){
console.log("我是content");
})
}
运⾏结果:我是content
     我是wrap
(addEventListener第三个参数写的是true,默认为false)
var wrap= ElementById("wrap");
var content= ElementById("content");
wrap.addEventListener("click", function(){
console.log("我是wrap");
}, true)
content.addEventListener("click", function(){
console.log("我是content");
})
}
运⾏结果:我是wrap
     我是content
第三个参数写的是true,则按照事件捕获的执⾏顺序进⾏。
9. 给 select 标签 option 内容加链接
<select onchange="window.open(options[selectedIndex].value, '_self')">
<option value="www.bj-hmk/">中⽂</option>
<option value="en.bj-hmk/">English</option>
</select>
10. Null 和 Undefined
undefined 表⽰根本不存在定义
null 表⽰⼀个值被定义了,定义为“空值”
(1)变量被声明了,但没有赋值时,就等于undefined。
(2)调⽤函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
所以设置⼀个值为 null 是合理的,如
objA.valueA = null;
但设置⼀个值为 undefined 是不合理的,如
objA.valueA = undefined; // 应该直接使⽤ delete objA.valueA; 任何⼀个存在引⽤的变量值为undefined都是⼀件错误的事情。
这样判断⼀个值是否存在,就可以⽤
objA.valueA === undefined // 不应使⽤ null 因为 undefined == null,⽽ null 表⽰该值定义为空值。
11. 解决slideDown()和slideUp()⿏标快速移⼊移出,出现反复执⾏的问题
⽅法⼀:
$(".orderDivMain").hover(function () {
if (!$(".orderDivId").is(":animated")) {
$(this).find('.orderDivId').slideDown(500);
}
}, function () {
if (!$(".orderDivId").is(":animated")) {
$(this).find('.orderDivId').slideUp(500);
}
});
⽅法⼆:
$(".orderDivMain").hover(function () {
$(".orderDivId").slideDown(500);
});
$(".orderDivId").mouseleave(function () {
$(".orderDivId").slideUp(500);
});
12. web应⽤整体性能的考虑
12 13两点参考于《JavaScript DOM编程艺术(第2版)》
尽量少访问DOM和尽量减少标记
ElementsByTagName("a").length > 0){
var links = ElementsByTagName("a");
for(var i = 0; i < links.length; i++){
<
}
}
上⾯这段代码使⽤了两次getElementsByTagName⽅法去执⾏相同的操作,浪费了⼀次搜索。更好的办法是把第⼀次搜索的结果保存在⼀个变量中,然后重⽤该结果:
var links = ElementsByTagName("a");
if(links.length > 0){
for(var i = 0; i < links.length; i++){
<
}
}
合并和放置脚本
<script src="js/functionA.js"></script>
<script src="js/functionB.js"></script>
<script src="js/functionC.js"></script>
<script src="js/function.js"></script>
上⾯两种做法,推荐的做法是把第⼀种functionA.js、functionB.js、functionC.js合并到⼀个脚本⽂件中。这样就可以减少加载页⾯时发送的请求数量,⽽减少请求数量通常都是性能优化时⾸先要考虑的。
位于<head>块中的脚本会导致浏览器⽆法并⾏加载其他⽂件,把<script>标签放在</body>标记之前,就可以让页⾯变的更快。
13. 使你所写的页⾯能够向后兼容、平稳退化
针对这⼀问题的最简单的解决⽅案是,检测浏览器对javascript的⽀持程度,即对象检测。⼏乎所有的东西(包括各种⽅法在内)都可以被当作对象来对待,这意味着我们可以很容易的把不⽀持某个特定的DOM⽅法的浏览器检测出来:
if(method){
statements
}
例如,检测浏览器是否⽀持getElementById⽅法:
ElementById){
statements using getElementById
}
但是如果需要检测多个DOM⽅法或者属性是否存在,那么最重要的语句可能会被深埋在⼀层⼜⼀层的花括号⾥,使得代码将会很难阅读和理解。
那么就可以把测试的条件改为“如果你不理解这个⽅法,请离开”则会变得简单明了。
if(!ElementById){
return false;
}
若需要测试多个⽅法或属性是否⽀持,可以使⽤“逻辑或”操作符将其合并:
if(!ElementById || !ElementsByTagName){
return false;
}
14. jQuery中attr和prop的区别
处理HTML元素本⾝就带有的固有属性时使⽤prop⽅法
处理HTML元素我们⾃⼰定义的Dom属性时使⽤attr⽅法
<input class='check1' type='checkbox'>选择1
<input class='check2' type='checkbox' checked>选择2
checked属于checkbox元素的固有属性,让我们来看看prop和attr的结果有什么不同:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。