原生JS面试题4

九、你对前端页面的性能优化有什么好的解决方案

1、CSS放在页面最上部(head标签中),JS 文件放在页面最下面
浏览器会在下载完成全部 CSS 之后 才对整个页面进行渲染, 因此最好的做法是将CSS 放在页面最上面(是将CSS放在head中),让浏览器尽快下载CSS。
js 文件则相反,浏览器在加载 js 后,立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此 js 最好放在页面最下面。但是,如果页面解析时就需要用到 js文件,这时放到底部就不合适了。

2、尽可能少的 设置 全局变量。

3、尽量减少DOM 操作

4、不要再标签中设置样式,最好 外部引用 CSS文件。

5、减少http 请求,合理设置 HTTP 缓存;(最有效的办法)
http协议是无状态的应用层协议,意味着每次 http 请求都需要建立通信链路、进行数据传输,而在服务器端,每个 http 都需要启动独立的线程去处理。这些通信和服务的开销都很昂贵,减少 http 请求的数目可有效提高访问性能。

减少http 的主要手段是 合并 CSS 、 合并 js 、 合并图片(多张图片合并成一张)。

设置HTTP 缓存: 缓存的力量是强大的,恰当的缓存设置可以大大的减少 HTTP请求。假设某网站首页,当浏览器没有缓存的时候访问一共会发出 78个请求,共 600多 K数据,而当第二次访问即浏览器已缓存之后访问则仅有 10个请求,共 20多 K数据。

怎样才能合理设置? 原则很简单,能缓存越多越好,能缓存越久越好。
如果可以的话,尽可能的将外部的脚本、样式进行合并,多个合为一个。另外, CSS、 Javascript、Image 都可以用相应的工具进行压缩,压缩后往往能省下不少空间。

6、使用浏览器缓存
对一个网站而言,CSS、js、logo、图标这些静态资源文件更新的频率都比较低,而这些文件几乎是每次 http 请求都需要的,如果将这些文件缓存在浏览器中,可以极好的改善性能。 通过设置 http 头中 的 cache-control 和 expires 的属性,可设定浏览器缓存,缓存时间可以是数天,甚至是几个月。

7、如果遇到大的文件,可以将文件放置在一个定时器中 ,利用异步操作,等其他的文件加载完成后,再加载 定时器中的文件。

8、CSS Sprites 合并 CSS 图片

9、 图片的懒加载
这条策略实际上并不一定能减少 HTTP 请求数,但是却能在某些条件下,或者页面刚加载时 减少 HTTP 请求数。对于图片而言,在页面刚加载的时候 ,可以只加载第一屏,当用户继续往后滚屏的时候,才加载后续的图片。

10、减少 cookie 传输 ,尽量使用 localStorage 存储 本地数据
一方面,cookie 包含在每次请求和响应中,太大的 cookie 会严重影响数据传输,因此哪些数据需要写入cookie 需要慎重考虑,尽量减少 cookie 中传输的数据量。

11、将 Image 进行压缩。

十、列举你常用的 JS 数组的原生方法,并用一句话去描述

1、push : 把一个元素 或 一组元素(数组)添加到当前数组的末尾。
2、pop :删除数组中最后一个元素,并返回删除的元素。
3、concat:该方法会把两个数组或元素组合在一起,但是不会改变调用者的结构。

var arr3 = arr1. concat ( arr2 );

4、splice :删除指定的元素,或者插入指定的元素。该方法有三个参数

第一个:index,表示要删除的开始下标;
第二个:表示要删除的元素个数;如果要增加元素,则设置为 0 ;
第三个:可选参数,从index 开始,要插入的元素。
该方法返回值是被删除掉的那部分数组。

     var arr1 = [1, 2, 3, 4, 5];
     var arr2 = arr1.splice(0, 2);
     alert(arr1); // [3, 4, 5]
     alert(arr2);  // [1, 2]

5、slice:返回指定数组的一个片段或子数组。里面可以传一个参数或两个参数,参数可以为正,也可以为负

第一个参数:表示开始的位置,索引。
第二个参数:数组索引结束为止(但不包含)。
如果有负数,则倒数第一个是 -1,倒数第二个是 -2,一次类推

6、reverse : 颠倒数组中元素的顺序;
7、join:返回一个字符串,字符串的内容是数组的所有元素,元素之间通过制定的分隔符进行分隔,分隔符就是join的参数
( unshift:在数组最前面添加一个元素或一组元素;shift :删除数组最前面一个元素,返回删除的元素)

列举你常用的 JS 字符串的原生方法,并用一句话去描述

十一、列举两个你工作中解决的业务难题
十二、你解决过哪些浏览器兼容性问题

1、不同浏览器的标签,默认的 margin 和 padding 不同,
解决方案:在 CSS 中 添加 *{ margin: 0 ; padding : 0 }
几乎所有的 CSS 文件开头都会用 通配符 * 来设置各个标签的 margin padding 为 0
2、各种特殊样式的兼容
比如 透明度、 圆角 、阴影 等。
特殊样式每个浏览器的代码 区别很大,所以,只能现查资料,通过给不同浏览器写不同的代码或者 前缀 来解决。
比如 透明度 opacity , IE 一下浏览器不能使用 opacity , 解决方法是:
opacity : 0.5; // 取值范围是 0 — 1
filter : alpha ( opacity = 50 ); 取值范围是 0 — 100

3、获取窗口大小或可视区域大小等方法不同

4、IE和 其他浏览器中的兼容
1)
HTML5Shiv 主要解决 HTML5提出的新元素不被IE6-8识别
IE9 以下浏览器 对 html5 新增标签不识别的问题。可以引入 一个外部 js 兼容文件,我的笔记上 记着

2)事件对象
DOM 0 级事件中,IE的event事件对象是window的一个属性,而其他浏览器中,事件对象作为事件处理函数的参数。
兼容写法: var evt = event || window.event;

3) 事件对象的事件源
浏览器中 event.target是触发的事件源,但IE中没有 target属性,但他有srcElement 属性,和 target 一样
兼容写法:var target = evt . target || evt . srcElement ;

4)添加 DOM 2级事件时。
浏览器通过 addEventListener( ) 添加监听事件,通过 removeEventListener( ) 方法 移除 监听的事件。
IE 中的添加 DOM 2级事件,通过 attachEvent( ) 添加监听事件,通过 detachEvent( ) 移除 监听的事件。

5)阻止冒泡行为
浏览器中阻止冒泡行为 是 通过 事件对象 event . stopPropagation( ) 方法阻止冒泡;
IE 中阻止冒泡的方法是 设置 事件对象的cancelBubble 属性为 ture
window . event .cancelBubble = true

6)阻止默认行为
浏览器中阻止默认行为是 事件对象的 preventDefault( )方法,
event . preventDefault ( );
IE中组织默认行为是 设置事件对象的returnValue 属性为 false
window . event . returnValue = false;

两者都兼容的, 还有一种方法,return false, 可以同时阻止冒泡行为和阻止默认行为

7)DOM 操作时,IE和其他浏览器获取 某元素的第一个子元素 或 最后一个子元素写法不同

5、polyfill

6、HTML5Shiv 主要解决 HTML5提出的新元素不被IE6-8识别

十三、如何使页面的动画效果更流畅?
十四、JS的事件机制或JS处理事件的过程

1、事件流 (捕获、冒泡)
事件流:指从页面中接收事件的顺序,有冒泡流和捕获流。
当页面中发生某种事件(如鼠标的点击)时,毫无疑问子元素和父元素都会受到该事件,可具体顺序是怎样的呢?冒泡和捕获则描述了两种不同的顺序。
冒泡:事件按照从 最特定的事件目标 到 最不特定的事件目标 (document)的顺序触发;
所有浏览器都支持冒泡事件,IE8以前只支持冒泡。

捕获:事件从 最不精确的对象(document)开始出发,然后到最精确。
虽然大多数浏览器都支持事件捕获,但很少有人使用

2、事件处理程序
DOM 0级事件处理程序:对于同一个dom节点而言,一种事件只能注册一个,后面注册的 同种事件会覆盖之前注册的。利用这个原理,我们可以解除事件, btn. onclick = null ;
以这种方式添加的事件处理程序,会在事件流的冒泡阶段被处理, 这样可以最大限度的兼容各种浏览器

DOM 2级事件处理程序:DOM 2级处理 支持同一个DOM元素注册多个同种事件,事件发生的顺序按照添加的顺序依次触发。DOM 2级事件通过 addEventListener 和 removeEventListener 管理

addEventListener 和 removeEventListener 两个方法都接收三个参数
第一个是" 事件名 "(注意不加 on ),
第二个是 事件触发时 的 函数,
第三个参数可选,是一个布尔值。默认为 false 时,false表示 事件在冒泡阶段调用。一般建议在冒泡阶段使用。ture为事件在 捕获阶段调用,只有 DOM 2级事件处理程序,才能是让事件在 捕获阶段调用
使用DOM2级方法 添加事件处理程序的主要好处是可以添加多个事件处理程序

注意:
通过 addEventListener( ) 添加的事件处理程序,只能使用 removeEventListener( ) 移除。
移除时,传入的参数与添加处理程序时使用的参数相同。这也意味着,通过 addEventListener()添加的 匿名函数 将无法移除

DOM2级规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。

首先发生的是事件捕获,为截获事件提供了机会

然后实际的目标接收到事件

然后冒泡阶段发生,事件又传播回文档

在DOM事件流中,实际的目标在捕获阶段不会接受任何事件 ,这意味着在捕获阶段,事件从 document 到 再到
后就停止了。 下一个阶段是 ”处于目标阶段“,于是事件在 div 元素上发生,并在事件处理中被看成冒泡阶段的一部分 即使 DOM2级事件
明确要求 捕获阶段 不会涉及事件目标,但大多数浏览器 都会在捕获阶段触发事件对象上的事件, 结果就是有两个机会在目标对象上面操作事件。

3、事件对象
触发某个事件时,会生产一个事件对象 event,这个对象包含了所有与事件有关的信息。常用的有与事件源 target , 利用 target 属性,可以实现事件委托,把这个事件 添加给父元素身上,因为冒泡机制,通过 target 判断触发的对象,从而实现后续操作。
例如: 点击任何一个 li ,该点击事件依然会冒泡到父元素 ul 上,所以直接将点击 li 后要做的事写到了父元素的点击事件里;通过 target 来判断事件源是否是 li 标签。

在IE中的事件对象
如果使用DOM0级 方法添加事件处理程序时,event对象作为 window 随想的一个属性存在:

btn.onclick = function(){
    var event = window.event;
    console.log(event.type) // click
}

如果事件处理程序是通过 attachEvent( ) 添加的,那么就会有一个 event 对象作为参数被传入事件处理程序的函数中:

btn.attachEvent("onclick", function(event){
    console.log(event.type) // click
})

所以在获取 事件对象的兼容性写法是:

btn.onclick = function(event) {
    var evt = event || window.event;
}

扩展:事件源 target 和 srcElement
IE浏览器中没有 event.target 属性,但是他的 event.srcElement 属性和 target 属性相同
所以获取事件源的兼容性写法:

var target = event.target || event.srcElement

4、IE事件处理程序
IE实现了与DOM中类似的链,各个方法:attachEvent( ) 和 detachEvent( )。
这两个方法接受相同的两个参数,事件处理程序名称与实践处理程序函数。
由于IE8及更早版本只支持事件冒泡,所以通过attachEvent( )添加的事件处理程序都会被添加到冒泡阶段
与 addEventListener()不同的是, attachEvent 第一个参数,事件处理程序名称要加“on”,

btn.attachEvent(“onclick”, function(){ });

` 注意:在IE中使用 attachEvent( ) 与使用 DOM 0级方法的主要区别在于事件处理程的作用域。在使用 DOM 0
级方法的情况下,事件处理程序会在其所属元素的作用域内运行。在使用
attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此this等于window。

btn.attachEvent("onclick",function(){
    alert( this === window ) // ture
})

与 addEventListener( ) 类似,attachEvent( ) 方法也可以用来为一个元素添加多个事件处理程序。但与 addEventListener( )不同的是,这些事件处理程序不是以添加他们的顺序执行,而是以相反的顺序被触发。
attachEvent( ) 事件通过 detachEvent( ) 来移除,条件是必须提供相同的参数、这也意味着添加的匿名函数将不能被移除。

5、跨浏览器的事件处理程序(兼容写法)
要保证处理事件的代码能在大多数浏览器下在一致地运行,只需要关心冒泡阶段。
兼容写法:

var EventUtil = {
    addHandler: function(element, type, handler){
        if( element.addEventListener){
            element.addEventListener(type, handler, false)
        }else if{ element.attachEvent }{
            element.attachEvent('on' + type, handler)
        }else{
            element['on' + type ] = handler;
        }
    },

    removeHandler: function(element, type, handler){
            if( element.removeEventListener){
            element.removeEventListener(type, handler, false)
        }else if{ element.detachchEvent }{
            element.detachEvent('on' + type, handler)
        }else{
            element['on' + type ] = null ;

        }
    }
}

//在使用时
var btn = document.getElementById('btn');
var handler = function(){
    console.log(this)
}

EventUtil.addHandler( btn, 'click', handler);
EventUtil.removeHandler( btn, 'click', handler)

6、阻止冒泡
用于立即停止事件在 DOM 层次中的传播,即取消进一步的事件捕获或冒泡。

FF : event.stopPropagation( ) 方法可以阻止冒泡
IE中阻止冒泡的方法:window.event.cancelBubble = true;

7、阻止默认行为;
比如阻止 a 标签的跳转等浏览器默认的行为
FF 中 通过 event.preventDefault( ) 方法阻止默认行为

link.onclick = function(event){
    event.preventDefault();
}

IE中阻止默认行为是 window.event.returnValue = false ;默认是true,

link.onclick = function(event){
    window.event.returnValue = false;
}

两者都兼容的暴力方法: return false
这个方法比较暴力,它会同时阻止事件冒泡 和 阻止默认行为
可以理解为 return false 等同于同时调用了

event.stopPropagation() 和 event.preventDefault()

十五、e.target 与 e.currentTarget 的区别
https://www.cnblogs.com/bo-haier/p/5644268.html
target与 currentTarget两者既然有区别,也有联系,下面是两个例子解释两者的区别

<!DOCTYPE html>
<html>
<head>
    <title>Example</title>
</head>
<body>
    <div id = 'A'>
        <div id = 'B'>
            
        </div>
    </div>
</body>
</html>


var a = document.getElementById('A');
var b = document.getElementById('B');

function handler(e){
    console.log(e.target);
    console.log(e.currentTarget);
}
a.addEventListener('click', handler, false);

当点击A时,输出:

<div id = 'A'> ... </div>
<div id = 'B'> ... </div>
当点击B时,输出:


<div id = 'B'> ... </div>
<div id = 'A'> ... </div>

也就是说,currentTarget 始终是 监听事件者 , 而 target 是 事件的 真正发出者。
换句话说,event.target指向引起触发事件的元素,而 event.currentTarget 则是事件绑定的元素

对象 this 、 currentTarget 和 target
在事件处理程序内部,对象 this 始终等于 currentTarget 的值, 而target 则只包含事件的实际目标。
如果直接将事件处理程序,指定给了目标元素, 则 this 、currentTarget 和 target 包含相同的值。
比如:

<input type = "button" id = "btn" value = "我是按钮" />
<script type = "text/javascript" >
    var btn = document.getElementById('btn');
    btn.onclick = function(e){
        console.log( e.currentTarget ) === this ); // ture
        console.log( e.target === this ) // ture  
    }
</script>

这个例子检测了 currentTarget 和 target 的值。由于 click 事件的目标就是按钮,因此,这三个值是相等的。

如果事件处理程序存在于按钮的 父节点 中,那么这些值是不相同的。看下面例子:

document.body.onclick = function(e){
    console.log( e.currentTarget === document.body ); // ture
    console.log( this === document.body ); // ture
    console.log( e.target === btn ); //ture
}

当单机这个例子中的按钮时, this 和 currentTarget 都等于 document.body , 因为事件处理程序是注册到这个元素的。
然而,target 元素却等于按钮元素,以为它是 click 事件真正的目标。由于按钮上并没有注册事件处理程序,结果 click 事件就冒泡到了
document.body ,在那里事件才得到了处理。

事件对象的 type 属性:在需要通过一个函数处理多个事件时,可以使用 type 属性。例如:

var btn = document.getElementById('btn');
var handler = function(event){
    switch ( event.type ){
        case "click":
            alert("Clicked");
            break;
        case "mouseover":
            event.target.style.backgroundColor = "orange";
            break;
        case "mouseout":
            event.target.style.backgroundColor = "";
            break
    }
}

btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;

十六、现在有一个场景,左边是菜单栏,右边是显示区域,点击菜单栏切换显示的内容,请尽可能多的说出你的方案。
https://blog.csdn.net/liule18235434869/article/details/82788533?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1

十七、eval是做什么的?

1、它的功能是把对应的字符串解析成 JS 代码并运行。
2、应该避免使用 eval ,不安全,非常耗性能 (2次,一次解析 JS 语句,一次执行)

十八、get 和 post 的区别

Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作。到这里,大家应该有个大概的了解了,GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。

1,http中,GET用于信息获取,而且是安全的和幂等的。

(1).所谓安全的意味着该操作用于获取信息而非修改信息。换句话说,GET 请求一般不应产生副作用。就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。

  • 注意:这里安全的含义仅仅是指是非修改信息。

(2).幂等的意味着对同一URL的多个请求应该返回同样的结果。

2,http中,POST是用于修改服务器上的资源的请求。

说完原理性的问题,我们从表面上来看看GETPOST的区别:

1. get是从服务器上获取数据,post是向服务器传送数据。
get 和 post只是一种传递数据的方式,get也可以把数据传到服务器,他们的本质都是发送请求和接收结果。只是组织格式和数据量上面有差别,http协议里面有介绍
2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
因为get设计成传输小数据,而且最好是不修改服务器的数据,所以浏览器一般都在地址栏里面可以看到,但post一般都用来传递大数据,或比较隐私的数据,所以在地址栏看不到,能不能看到不是协议规定,是浏览器规定的。
3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
没明白,怎么获得变量和你的服务器有关,和get或post无关,服务器都对这些请求做了封装
4. get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。
post基本没有限制,我想大家都上传过文件,都是用post方式的。只不过要修改form里面的那个type参数
5. get安全性非常低,post安全性较高。
如果没有加密,他们安全级别都是一样的,随便一个监听器都可以把所有的数据监听到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值