前端常见JS问题总结

心系少时言 等一不归人

23. 刷新当前页并跳转到登录页

window.location.href = `${window.location.protocol}//${window.location.host}/login`;

22. JavaScript自定义事件

var eve = new Event("test"),
    ev = document.getElementById("ev");
ev.addEventListener("test", function (){
    console.log("test dispatch");
});

ev.dispatchEvent("eve"); 

21. 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

21. addEventListener 和 attachEvent 区别

attachEvent方法适用于IE
attachEvent中的事件带on, 而addEventListener中的事件不带on
attachEvent 方法有两个参数:第一个参数为事件名称,第二个参数为接收事件处理的函数; addEventListener 方法有三个参数:第一个参数为事件名称(不含 on,如 "click"),第二个参数为要接收事件处理的函数,第三个参数为一个bool值,默认为false

1. 添加多个事件处理程序执行的顺序不同
js代码(addEventListener): 
var btn=document.getElementById("myBtn");  
btn.addEventListener("click",function(){  
    alert(1);     
    },false);  
  
btn.addEventListener("click",function(){  
      alert(2);     
    },false); 

//执行结果 1 ,2
js代码(attachEvent): 
var btn=document.getElementById("myBtn");  
 btn.attachEvent("onclick",function(){  
     alert(1);     
   });  
 btn.attachEvent("onclick",function(){  
     alert(2);     
   });  

//执行结果 2 ,1
2. 事件处理程序的作用域不同

DOM2级事件添加的事件处理程序,它的作用域是所属的元素,而IE的事件处理程序会在全局作用域中运行。

js代码(addEventListener): 
var btn=document.getElementById("myBtn");  
btn.addEventListener("click",function(){  
    console.log(this.id);    // myBtn   
    },false);  
js代码(attachEvent): 
var btn=document.getElementById("myBtn");  
btn.attachEvent("onclick",function(){  
  alert(this===window);    // true   
  });  
3. 移除绑定事件 removeEventListener() 和 detachEvent()
移除 addEventListener 事件:
element.removeEventListene(event, function, useCapture)
event: 事件名,注意不使用“on”前缀,如 click
function: 指定事件触发时执行的函数
useCapture: 指定事件是否在捕获或冒泡阶段执行
true: 在捕获阶段执行
false: 在冒泡阶段进行,默认值为false
如果添加时用的捕获阶段,那么在移除时也要用捕获阶段,否则无法移除它们
如果是同一个元素同一个调用函数同一个useCapture值绑定多次,在移除时只需要执行一次移除
移除 attachEvent 事件:
element.detachEvent(event, function)
event: 事件名,注意要使用“on”前缀,如 onclick
function: 指定事件触发时执行的函数

20. addEventListener 和 on 区别

html代码:
<div id="box">addEventListener 和 on 区别</div>
js代码:
window.onload = function(){
     var box = document.getElementById("box");
     box.onclick = function(){
         console.log("我是box1");
     }
     box.onclick = function(){
         console.log("我是box2");
     }
}

//运行结果:“我是box2”
js代码:
 window.onload = function(){
     var box = document.getElementById("box");
     box.addEventListener("click", function(){
         console.log("我是box1");
     })
     box.addEventListener("click", function(){
         console.log("我是box2");
     })
}
运行结果:我是box1
     我是box2

第二个onclick会把第一个onclick给覆盖了,虽然大部分情况我们用on就可以完成我们想要的结果,但是有时我们又需要执行多个相同的事件,很明显如果用on完成不了我们想要的,而addEventListener可以多次绑定同一个事件并且不会覆盖上一个事件

19. HTML5 新增的事件

  1. contextmenu事件
    这个事件是当鼠标右击的时候触发的,但是触发这个属性的时候默认的行为也会被触发,所以需要通过preventDefault()方法来阻止。
  1. beforeunload事件
    beforeunload在页面卸载之前触发,该事件会弹出一个对话框,询问是否确定离开。
  1. hashchange事件
    该事件当URL中的hash值改变时触发,通常用于Ajax应用中利用URL参数保存导航信息;这个在前端路由的制作中是非常有用得。

18. 阻止事件默认行为和阻止事件冒泡

html代码:
<div id="wrap" style="width: 200px; height: 200px; background: gray;">
    <div id="btn" style="width: 100px; height: 100px; background: orangered;"></div>
    <a id="prevent" target="_blank" href="http://www.baidu.com">preventDefault</a>
</div>
标准浏览器的使用方法

preventDefault(): 用于阻止事件的默认行为;
比如: a 链接的跳转行为和表单自动提交行为

js代码: 
var prevent = document.getElementById("prevent");
    prevent.addEventListener("click", function(event){
        event.preventDefault();
    }, false);

//使用preventDefault()方法就阻止了a标签打开新窗口的默认行为 

stopPropagation(): 用于阻止事件的进一步获取和传播;
比如:阻止事件继续向上层冒泡

js代码:
var btn = document.getElementById("btn"),
    wrap= document.getElementById("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.returnValue = false;   //阻止事件的默认行为;
event.cancelBubble = true;   //阻止事件的进一步获取或者冒泡;
使用示例
js代码: 
function prevent(event) {
    event = event || window.event;
    if(event.preventDefault) {
        event.preventDefault();
    } else {
        event.returnValue = false; 
    }
}
//使用 if else 去判断

17. 事件捕获和事件冒泡

事件冒泡执行过程:从最具体的的元素(你单击的那个元素)开始向上开始冒泡,下面的案例的顺序是:content > wrap
事件捕获执行过程:从最不具体的元素(最外面的那个盒子)开始向里面冒泡,下面的案例的顺序是:wrap > content

html代码:
<div id="wrap">
    <div id="content"></div>
</div>
js代码: (addEventListener第三个参数写的是false, 默认为false)
 window.onload = function(){
     var wrap= document.getElementById("wrap");
     var content= document.getElementById("content");
     wrap.addEventListener("click", function(){
         console.log("我是wrap");
     }, false)
     content.addEventListener("click", function(){
         console.log("我是content");
     })
}
运行结果:我是content
     我是wrap
js代码: (addEventListener第三个参数写的是true, 默认为false)
  window.onload = function(){
     var wrap= document.getElementById("wrap");
     var content= document.getElementById("content");
     wrap.addEventListener("click", function(){
         console.log("我是wrap");
     }, true)
     content.addEventListener("click", function(){
         console.log("我是content");
     })
}
运行结果:我是wrap
     我是content

第三个参数写的是true,则按照事件捕获的执行顺序进行。

16. 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 表示该值定义为空值。

15. 键盘事件属性

event.keyCode;    // 获取按下的键盘按键的键码值(Unicode值)
event.ctrlKey;    // 获取是否按下了ctrl键
event.shiftKey;   // 获取是否按下了shift键
event.altKey;     // 获取是否按下了alt键
event.metaKey;    // 获取是否按下了meta键

14. 鼠标事件属性

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    // 获取指定事件上哪个键盘键或鼠标按钮被按下

13. 给 select 标签 option 内容加链接

<select onchange="window.open(options[selectedIndex].value, '_self')">
    <option value="http://www.bj-hmk.com/">中文</option>
    <option value="http://en.bj-hmk.com/">English</option>
</select>

12. 解决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);
});

11. web应用整体性能的考虑

10 11两点 参考于 《JavaScript DOM编程艺术(第2版)》

尽量少访问DOM和尽量减少标记

if(document.getElementsByTagName("a").length > 0){
    var links = document.getElementsByTagName("a");
    for(var i = 0; i < links.length; i++){
        something...
    }
}

上面这段代码使用了两次getElementsByTagName方法去执行相同的操作,浪费了一次搜索。更好的办法是把第一次搜索的结果保存在一个变量中,然后重用该结果:

var links = document.getElementsByTagName("a");
if(links.length > 0){
    for(var i = 0; i < links.length; i++){
        something...
    }
}

合并和放置脚本

<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>标记之前,就可以让页面变的更快。

10. 使你所写的页面能够向后兼容、平稳退化

针对这一问题的最简单的解决方案是,检测浏览器对javascript的支持程度,即对象检测。几乎所有的东西(包括各种方法在内)都可以被当作对象来对待,这意味着我们可以很容易的把不支持某个特定的DOM方法的浏览器检测出来:

if(method){
    statements
}

例如,检测浏览器是否支持getElementById方法:

if(document.getElementById){
    statements using getElementById
}

但是如果需要检测多个DOM方法或者属性是否存在,那么最重要的语句可能会被深埋在一层又一层的花括号里,使得代码将会很难阅读和理解。

那么就可以把测试的条件改为“如果你不理解这个方法,请离开”则会变得简单明了。

if(!document.getElementById){
    return false;
}

若需要测试多个方法或属性是否支持,可以使用“逻辑或”操作符将其合并:

if(!document.getElementById || !document.getElementsByTagName){
    return false;
}

9. 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的结果有什么不同:

prop方法:
$('.check1').prop('checked') -- false
$('.check2').prop('checked') -- true 
attr方法:
$('.check1').attr('checked') -- undefined 
$('.check2').attr('checked') -- 'checked'

8. 在选中的元素上绑定事件和通过代理绑定事件的区别

在选中的元素上绑定click事件:
$('a').on('click', function(){});
通过代理绑定click事件:
$(document).on('click', 'a', function(){});

在选中的元素上绑定事件只能为页面现有的a元素绑定点击事件,如果是动态生成的新的a元素是没有事件的。

通过代理绑定事件是将指定的事件绑定在document上,新添加的a元素也能触发此事件。

7. reload 方法,强迫浏览器刷新当前页面。

语法:location.reload([falseOrTrue]) ;
参数: falseOrTrue, 可选参数。 默认为 false,从客户端缓存里取当前页。true,则以 GET 方式,从服务端取最新的页面,相当于客户端点击 F5(“刷新”)。

html代码:
    <a href="javascript:location.reload();">点击刷新页面</a>
    <span onclick="location.reload(true);">点击刷新页面</span>

6. 禁止页面选取内容

适用于IE、Chrome浏览器,在 head 的 <script> 标签里面添加 js 代码

js代码:
document.onselectstart = function (e) { return false; }
或者
document.onselectstart = new Function('event.returnValue = false;');

在firefox火狐浏览器中,禁止元素被选取可以采用 CSS 样式在来控制

CSS代码:
body{
    -moz-user-focus: ignore;  
    -moz-user-input: disabled; 
    -moz-user-select: none;
}

禁止鼠标右键

js代码:
document.oncontextmenu = function(e){return false;}

5. 正则表达式验证

//  验证是否为手机号
function phone(num) {
    return /^1[34578]\d{9}$/.test(num);
}

//  验证是否为邮箱
function email(e) {
    return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(e);
}

4. 返回顶部

js代码:
window.onscroll = function () {
    if (document.body.scrollTop || document.documentElement.scrollTop > 0) {
        document.getElementById('back_top').style.display = "block";
    } else {
        document.getElementById('back_top').style.display = "none";
    }
}
$('.back_top').click(function () {
    $("html,body").animate({ scrollTop: 0 }, 500);
    return false;
});

3. js 中 Error 错误

ReferenceError:作用域判别错误,通过作用域链的搜寻找不到相应的变量。
TypeError:可以通过作用域搜索到变量,但是对变量的操作不合法。
SyntaxError:语法错误。

2. 获取当前时间

var newDate,
    myDate = new Date(),
    year = myDate.getFullYear(),
    month = myDate.getMonth() + 1,  /*获取当前月份(0-11, 0代表1月)*/
    day = myDate.getDate(),
    hour = myDate.getHours(),
    minute = myDate.getMinutes(),
    second = myDate.getSeconds();
    if(month < 10){
        month = '0' + month;
    }
    if(day < 10){
        day = '0' + day;
    }
    if(hour < 10){
        hour = '0' + hour;
    }
    if(minute < 10){
        minute = '0' + minute;
    }
    if(second < 10){
        second = '0' + second;
    }
    newDate = year + '/' + month + '/' + day + " " + hour + ":" + minute + ":" + second;
yy/mm/dd hh:mm:ss

1. 点击div触发select显示下拉框

<div class="selectBox">
    <div class="selectTxt">+86</div>
    <select class="select">
        <option>美国 +1</option>
        <option>韩国 +82</option>
        <option>中国 +86</option>
        <option>香港 +852</option>
    </select>
</div>
/*下拉样式*/
.select, 
.selectTxt{
    display: block;
    width: 1.1rem;
    height: .6rem;
    line-height: .57rem;
    border:0;
    border-bottom: .03rem solid #bac1cf;
    font-size: .3rem;
    font-family: $ff-GothamLight;
    background: url("images/dropdown.svg") no-repeat right center;
    background-size: 100%;
    padding-right: .22rem;
}
select{
    appearance: none;
    -moz-appearance: none;
    -webkit-appearance: none; 
}
select::-ms-expand {
    display: none;
}
/*定位 覆盖select显示的内容,用selectTxt替换select显示的内容*/
.selectBox{
    position: relative;
}
.selectBox .selectTxt,
.selectBox .select{
    position: absolute;
    left: 0;
    top: 0;
    pointer-events: none;
}
.selectBox .selectTxt{
    z-index: 2;
    background-color: #f1f4f7;
}
.selectBox .select{
    z-index: 1;
}
$(document).on("change", ".select", function () {
    var $thisTxt = $(this).val().split("+"),
        $selectTxt = $thisTxt[$thisTxt.length - 1];
    $(this).siblings(".selectTxt").text("+" + $selectTxt);
});
下拉框中显示国家和区号,选中之后只展示区号
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • <a name='html'>HTML</a> Doctype作用?标准模式与兼容模式各有什么区别? (1)、<...
    clark124阅读 3,418评论 1 19
  • 在线阅读 http://interview.poetries.top[http://interview.poetr...
    程序员poetry阅读 113,828评论 24 450
  • 前端开发面试知识点大纲: HTML&CSS: 对Web标准的理解、浏览器内核差异、兼容性、hack、CSS基本功:...
    秀才JaneBook阅读 2,247评论 0 25
  • 几首小诗,写给你我。 一段生活,一些感受。 生活不尽如意,过去的也终将过去, 还是浅笑四五度,然后继续前行。 -0...
    随绛阅读 455评论 6 6
  • 我们的骨灰注定散落 在南北东西 耳朵和眼睛 装满异乡的烟火 背包日渐沉重 甚至迈不动双腿 很多人平凡死去 很多人血...
    奔跑的艾略特高阅读 515评论 3 51