精华内容
下载资源
问答
  • 原生JS面试题

    千次阅读 2019-03-29 20:41:00
    面试中遇到的原生js题总结 1、js 去重1) indexOf Array.prototype.unique = function(){ var result = []; var len = this.length; for(var i = 0; i<len; i++){ if(result.indexOf(this[i])&...

    面试中遇到的原生js题总结

     

    1、js 去重
    1) indexOf

    Array.prototype.unique = function(){
        var result = [];
        var len = this.length;
        for(var i = 0; i<len; i++){
            if(result.indexOf(this[i])<0){
                result.push(this[i]);
            }
        }
        return result;
    }
    var arr = [1,2,3,2,1,3,2,1];
    arr.unique();//arr = [1,2,3]
    • 在IE6、7、8不支持indexOf方法,可以在Array原型链上扩展indexOf方法
    if(!Array.prototype.indexOf){    
       Array.prototype.indexOf = function(val){    
           var value = this;    
           for(var i =0; i < value.length; i++){    
              if(value[i] == val) return i;    
           }    
          return -1;    
       };    
    }  

    2)数组先排序

    Array.prototype.unique = function(){
        this.sort();
        var result = [this[0]];
        var len = this.length;
        for(var i = 0; i<len; i++){
            if(this[i] !== result[result.length-1]){
                result.push(this[i]);
            }
        }
        return result;
    }
    var arr = [1,2,3,2,1,3,2,1];
    arr.unique();//arr = [1,2,3]

    3)ES6新方法set和Array.from

    function unique(arr){
      return Array.from(new Set(arr));
    }
    • set是一种新的数据结构,它可以接收一个数组或者是类数组对象,自动去重其中的重复项目,返回的是json对象
    • Array.from可以把类数组对象、可迭代对象转化为数组

    2、js 字符串转为驼峰法

    function tansform(str){
        var re = /-(\w)/g;
        return str.replace(re,function($0,$1){//replace 中正则表达式$0,$1,$n等代表正则表达式内小括号的匹配值,从$1开始,$0代表正则表达式的整体值
            return $1.toUpperCase();
        });
    }
    var str = 'border-left-color';
    tansform(str);//borderLeftColor

    3、查找字符串中最多的字符及个数

    function repeatCharNum(str){
        var arr = str.split('');
        str = arr.sort().join('');
        var re = /(\w)\1+/g;
        var index = 0;
        var value = '';
        str.replace(re,function($0,$1){
            if(index < $0.length){
                index = $0.length;
                value = $1 ;
            }
        });
        alert ('最多字符'+value+'出现的次数'+index);
    }

    4、编写一个函数,将输入的参数中的数字字符追加为一个数字字符串,参数输入不确定

    function getStrChange(){
      var len = arguments.length;//参数不确定时使用arguments关键字
      var re = /^\d+$/;
      var str = '';debugger;
      for(var i =0; i< len; i++){
        if(!(re.test(arguments[i]))){ 
          continue;
        }
        if(i == len-1){
          str = str+arguments[i];
        }else{
          str = str+arguments[i]+',';
        }  
      }
      return str;
    }
    alert(getStrChange('1','a','45','b','3',1));//('1,45,3,1')

    5、var和function的预解析问题,以及变量和function的先后顺序的问题

     // 以下代码执行输出结果是什么
        function b () {
            console.log(a);// function a(){}
            var a = 10;
            function a() {};
            a = 100;
            console.log(a);//100
        }
        b();
    
        function c () {
            console.log(a);//function a(){}
            function a() {};
            var a = 10;
            a = 100;
            console.log(a);//100
        }
        c();
    
        (function d (num) {
            console.log(num);//100
            var num = 10;
        }(100))
    
        (function e (num) {
            console.log(num);//function num () {};
            var num = 10;
            function num () {};
        }(100))
    
        (function f (num) {
            function num () {};
            console.log(num);//function num () {};
            var num =10
            console.log(num);//10
        }(100))
    
        //仍然是预解析(在与解析过程中还要考虑一下当前变量的作用于)
        function m () {
            console.log(a1); // underfined
            console.log(a2); // underfined
            console.log(b1); // underfined
            console.log(b2); // underfined
            if(false) {
                function b1 (){};
                var a1 = 10;
            }
            if(true) {
                function b2 (){};
                var a2 = 10;
            }
            console.log(a1); // underfined
            console.log(a2); // 10
            console.log(b1); // underfined
            console.log(b2); // function
        }
        m();
    
        function n() {
            if(2>1) {
                arr = 10;
                brr = 10;
                let arr;//要在严格模式'use strict'下运行
                var brr;
                console.log(arr);
                console.log(brr);
            }
        }
        n(); // ReferenceError
    • 函数声明:function a(){}可以提前解析;
    • 函数表达式:var b = function a(){} : 命名函数表达式
      var b = function (){} :匿名函数表达式
      (function a(){}) : 表达式
      位运算符:(为了区分函数表达式和函数声明)
      ~funtion a(){} : 表达式
      -funtion a(){} : 表达式
      +funtion a(){} : 表达式
      !funtion a(){} : 表达式
      (不可以被提前解析)
    • 函数表达式和函数声明的区别:函数声明可以提前被解析,函数表达式不可以,需要在引用前提前声明;函数表达式可以直接后面加括号执行,函数声明不可以。
    • let关键字要在严格模式'use strict'下运行

    6、判断数据类型

       function gettype(nm){
        return Object.prototype.toString.call(nm);
    } 
       console.log(gettype(3)); //[object number]
    • js基础数据类型:number string null undefined string boolean,存放在栈内存
    • js引用数据类型:Object (Array,Date,RegExp,Function),存放在堆内存

    7、如何将arguments转为array

    function changeArg(arguments){
        return Array.prototype.slice.apply(arguments);
    }

    8、如何判断array对象
    可以使用Array.isArray()或者Object.prototype.toString.call()判断

    9、原生dom实现删除dom结点

    function deleteNode(node){
        if(!node) return;
        if(node.parentNode){
            node.parentNode.removeChild(node);
        }
    }

    10、给button绑定click事件

    var x = document.getElementById("myBtn");
    if (x.addEventListener) {                    //所有主流浏览器,除了 IE 8 及更早 IE版本
        x.addEventListener("click", myFunction);
    } else if (x.attachEvent) {                  // IE 8 及更早 IE 版本
        x.attachEvent("onclick", myFunction);
    }
    • 还可以用onclick()绑定,但是onclick()混合了js和html,不建议使用。
    • addEventListener("click", function,useCapture),useCapture默认false,代表事件冒泡阶段执行,true代表事件捕获阶段执行。
    • addEventListener和onclick的区别:addEventListener可以添加多个事件,不会被覆盖;onclick只可以一个事件,重复添加,后面一个会覆盖前面一个的事件。

    11、排序算法
    1)冒泡排序

         相邻元素两两对比然后元素交换

    function bubbleSort(arr){

      for(var i = 0;i< arr.length-1;i++){
        for(j=i+1;j<arr.length;j++){
          if(arr[i]>arr[j]){
            var temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
          }
        }
      }
      return arr;
    }

    2)快速排序

    获取数组中间的索引 获取数组中间项

    function quickSort(arr){
      if(arr.length<=1){
        return arr;
      }
      var len = Math.floor(arr.length/2);
      var cur = arr.splice(len,1);
      var left = [];
      var right = [];
      for(var i=0;i<arr.length;i++){
        if(cur>arr[i]){
          left.push(arr[i]);
        }else{
          right.push(arr[i]);
        }
      }
      return quickSort(left).concat(cur,quickSort(right));
    }

    3)选择排序(Selection sort)

    是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
    for(var i=0;i<arr.length;i++){//按顺序假设每一个值都是最小值。
    var minindex=i;//假设的最小值的索引下标
    var minvalue=arr[minindex];//假设的最小值
    for(var j=i+1;j<arr.length;j++){
    if(minvalue>arr[j]){//数组项的值比假设的最小值还要小,当前这项就是最小值
    minvalue=arr[j];
    minindex=j;
    }
    }
    //如果获取到了最小值,和假设的最小值进行交换。
    if(minindex!=i){//防止假设的真的是最小值,无需自己和自己进行交换。
    var temp=arr[i];
    arr[i]=arr[minindex];
    arr[minindex]=temp;
    }

    }

     

    
    

    转载于:https://www.cnblogs.com/cqgxlove/p/10623797.html

    展开全文
  • 原生js面试题

    2019-09-22 05:18:12
    1、线程与进程的区别 一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了...

    1、线程与进程的区别

    一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。

    另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

    线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

    从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

    2、你如何对网站的文件和资源进行优化?

    期待的解决方案包括:文件合并文件最小化/文件压缩使用CDN托管缓存的使用(多个域名来提供缓存)其他。

    3、请描述一下cookies,sessionStorage和localStorage的区别?

    sessionStorage和localStorage是HTML5 Web Storage API提供的,可以方便的在web请求之间保存数据。有了本地数据,就可以避免数据在浏览器和服务器间不必要地来回传递。sessionStorage、localStorage、cookie都是在浏览器端存储的数据,其中sessionStorage的概念很特别,引入了一个“浏览器窗口”的概念。sessionStorage是在同源的同窗口(或tab)中,始终存在的数据。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一页面,数据仍然存在。关闭窗口后,sessionStorage即被销毁。同时“独立”打开的不同窗口,即使是同一页面,sessionStorage对象也是不同的cookies会发送到服务器端。其余两个不会。Microsoft指出InternetExplorer8增加cookie限制为每个域名50个,但IE7似乎也允许每个域名50个cookie。

    • Firefox每个域名cookie限制为50个。

    • Opera每个域名cookie限制为30个。

    • Firefox和Safari允许cookie多达4097个字节,包括名(name)、值(value)和等号。

    • Opera允许cookie多达4096个字节,包括:名(name)、值(value)和等号。

    • InternetExplorer允许cookie多达4095个字节,包括:名(name)、值(value)和等号。

    4、描述下“reset”CSS文件的作用和使用它的好处。

    因为浏览器的品种很多,每个浏览器的默认样式也是不同的,所以定义一个css reset可以使各浏览器的默认样式统一。

     

    5、解释下JavaScript中this是如何工作的。

    this永远指向函数运行时所在的对象,而不是函数被创建时所在的对象。匿名函数或不处于任何对象中的函数指向window 。

    • 1.如果是call,apply,with,指定的this是谁,就是谁。

    • 2.普通的函数调用,函数被谁调用,this就是谁。

    6、call和.apply的区别是什么?

    call方法: 
    语法:call(thisObj,Object) 
    定义:调用一个对象的一个方法,以另一个对象替换当前对象。 
    说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。 
    apply方法: 
    语法:apply(thisObj,[argArray]) 
    定义:应用某一对象的一个方法,用另一个对象替换当前对象。 
    说明:如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

    对于apply和call两者在作用上是相同的,但两者在参数上有以下区别: 
    对于第一个参数意义都一样,但对第二个参数:apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])同时使用apply的好处是可以直接将当前函数的arguments对象作为apply的第二个参数传入。

     

    转载于:https://www.cnblogs.com/yangshuzhong/p/11458059.html

    展开全文
  • 原生JS面试题4

    2020-04-22 12:08:13
    九、你对前端页面的性能优化有什么好的解决方案 1、CSS放在页面最上部(head标签中),...js 文件则相反,浏览器在加载 js 后,立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此 js 最好放在页面最下面。但...

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

    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安全性较高。
    如果没有加密,他们安全级别都是一样的,随便一个监听器都可以把所有的数据监听到。

    展开全文
  • 原生JS面试题2

    2020-04-22 11:17:18
    三、js跨域问题怎么解决? 1、 JSONP跨域请求 要理解跨域,先要了解一下”同源策略“。所谓同源是指,协议、域名、端口都相同。所谓”同源策略“,简单的说,就是基于安全考虑,当前域不能访问其他域的东西。 http ...

    三、js跨域问题怎么解决?
    1、 JSONP跨域请求
    要理解跨域,先要了解一下”同源策略“。所谓同源是指,协议、域名、端口都相同。所谓”同源策略“,简单的说,就是基于安全考虑,当前域不能访问其他域的东西。
    http 和 https :协议不同
    www.a.com 和 www.b.com :域名不同
    www.a.com : 8080 和 www.a.com : 1000 : 端口不同

    在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的。
    例如我们在自己的网站通过 ajax 去 获取豆瓣上的图书接口:
    https://api.douban.com/v2/book/search?q=javascript&count=1

    我们通过以上 ajax 去访问,发现运行时会报错:
    在这里插入图片描述
    只要出现这个错误,就说明服务器接口不支持跨域
    //No ‘Access-Control-Allow-Origin’ header is present on the requested resource
    这是因为不同源,所以无法访问其他服务器的数据

    但是 img的 src ( 获取图片 ) , link 的 href (获取css),script 的 src (获取js)这三个属性都不符合同源策略,它们可以跨域获取数据。JSONP就是利用script 的 src 来实现跨域获取数据。

    跨域原理
    JSONP实现跨域请求的原理,简单的说,就说动态创建
    script标签,然后利用script的 src 不受同源策略的约束来跨域获取数据。
    JSONP 由两部分组成:回调函数和数据。回调函数 是当响应到来时,应该在页面中调用的函数。回调函数的名字,一般是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。

    注意:JSONP不是真正的 ajax
    ajax是异步的,jsonp是同步的,所以它不是真正的ajax

    动态创建 script>标签,设置其 src ,回调函数在 src 中设置:

    var script = document.createElement("script");
    script.src = "https://api.douban.com/v2/book/search?q=javascript&count=1";
    document.body.insertBefore( script, document.body.firstChild );
    

    在页面中,返回的 JSON 作为参数传入 回调函数中,我们通过回调函数来 操作数据

    function handleResponse(response){
        //对 response 数据进行操作代码
    }
    

    了解了 JSONP 的基本使用方法,我们在实现上面,通过 ajax 调用豆瓣接口的需求,实现代码如下:
    在这里插入图片描述
    注意:以上代码中,要记得成功访问完数据后,要删除创建的动态 script标签:document.body.removeChild(script)

    其实在接口数据的形式类似:fn( { name: “张三” , age: “20” } ) ,我们传递过去一个和这个函数名字相同的回调函数,参数就是访问到的数据。
    假如接口是:

    http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice

    函数名就是 callbanck = 的值:refreshPrice.

    JSONP目前还是比较流行的跨域方式,虽然JSONP使用起来方便,但是也存在一些问题:如果其他域不安全,很可能会在响应中夹带一些恶意代码。而且要确定 JSONP请求是否失败并不容易。
    JSONP有个限制,只能用GET请求,并且要求返回JavaScript

    更多跨域的方法介绍:
    https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434499861493e7c35be5e0864769a2c06afb4754acc6000
    对ajax有更进一步的理解,利用cros进行跨域处理!!!

    2、CROS跨域

    3、反向代理

    四、闭包
    概念:闭包就是能够读取其他函数内部变量的函数
    由于函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”(然后将这个内部的函数 return 返回出来)。
    所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁

    闭包的作用:它最大的用处有两个: 1) 一个是可以读取函数内部的变量;
    2) 另一个就是让这些变量的值始终保存在内存中。

    使用闭包的注意点:1) 由于闭包会使得函数中的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄漏。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

    内存泄漏:程序的运行需要内存。对于持续运行的服务进程,必须及时释放不再用到的内存,否则占用越来越高,轻则影响系统性能,重则导致进程崩溃。不再用到的内存,没有及时释放,就叫做内存泄漏。
    http://www.ruanyifeng.com/blog/2017/04/memory-leak.html

    2) 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要小心,不要随便改变父函数内部变量的值。

    五、promise的用法和原理?
    概念:promise 是异步编程的一种解决方案。它可以把异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
    Promise 为异步操作提供了统一的接口,使得控制异步操作更加容易,它的强大之处在于它的链式调用。

    基本用法:

    new Promise(function(resolve, reject) {
    //待处理的异步逻辑
    //处理结束后,调用resolve或reject方法
    })
    

    新建一个promise很简单,只需要new 一个 Promise 对象即可。所以promise本质上就是一个函数,它接受一个函数作为参数,并且返回promise对象,这就给链式调用提供了基础。

    特点:
    1、对象的状态不受外界影响。 Promise 的实例 有以下三种状态: 1)pending : 进行中 2)resolved : 已成功完成 3)rejected : 已失败

    只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

    2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为resolved;从pending变为rejected。 只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。
    基本用法:
    ES6规定,Promise 对象是一个构造函数,用来生成Promise
    实例
    在这里插入图片描述

    Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript 引擎提供, 不是自己部署。

    resolve函数的作用,将Promise对象的状态从“进行中”变成 “成功”( 即从pending变为resolved ) ,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。
    reject函数的作用,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

    Promise实例生成以后,可以用then方法分别制定 Resolved状态和Rejected状态的回调函数:
    在这里插入图片描述

    then方法可以接受 2 个回调函数作为参数,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。

    promise捕获错误 .catch方法:

    Promise.prototype.catch方法是Promise.prototype.then(null,
    rejection)的别名,用于指定发生错误时的回调函数。

    在这里插入图片描述
    Promise对象的错误具有“ 冒泡 ”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。
    在这里插入图片描述
    题外话:async 函数是es7 提案出来的语法, async函数是用来取代回调函数的另一种方法。

    展开全文
  • 原生JS面试题1

    2020-04-20 22:07:31
    答案: 第一: 因为 person1.proto === person1 的构造函数.prototype 因为 person1的构造函数 === Person 所以 person1.proto === Person.prototype 第二: 因为 Person.proto === Person的构造函数.prototype...
  • 原生JS面试题3

    2020-04-22 11:21:28
    七、用原生 js 实现懒加载 1、 懒加载的概念:在图片非常多的应用场景,为了提高也没面加载速度,改善用户体验,我们对未出现在视野范围内的图片先不进行加载,等到出现在视野范围才去加载。 2、为什么要懒加载:懒...
  • 原生JS面试题5

    2020-04-22 12:08:35
    十九、简述 ajax 的过程 1. 创建XMLHttpRequest对象,也就是创建一个异步调用对象 2. 创建一个新的HTTP请求,并...5. 获取异步调用返回的数据 6. 使用JavaScript和DOM实现局部刷新 ...分别代表什么? 200 - 请求成功 3...
  • 三道原生js面试题(面向高级)

    千次阅读 2018-07-23 17:21:22
    独乐乐不如众乐乐,分享给大家,共同提升对原生js的理解~ 话不多说,亮~ 大家如果有更好的实现方法欢迎提出探讨~   1.编写curry.js 实现函数的分步调用 var curry = require('./curry.js');// &lt;- ...
  • <script type="text/javascript" src="js/tools.js"> //变量声明提升: //一、先看一段代码: //以下这段代码,因为,没有用var声明,所以出错 /* function testf(){ console.log(myName);//这句话会提示 myName ...
  • //一、 for(var i=1;i&lt;=3;i++){  setTimeout(function(){  console.log(i);  },0);...// 虽然 setTimeout的时长是0,但是,也是启动了异步操作,而JavaScript本身是单线程的。...//所以,setTimeout的回调函数...
  • <script type="text/javascript" src="js/tools.js"> //全局变量和局部变量重名,并带有变量声明提升。 /* var age = 250;//定义一个全局变量age,赋值为250 function testf(){ console.log("testf:age="+age);/...
  • 或者说,js代码执行时,查找变量的范围。 ES5及其以前: JS的变量作用域分为:全局作用域和函数作用域(局部作用域) 在google的控制台里,可以看到 、用var 声明的变量a1是全局变量,是window对象的属性 、...
  • <script type="text/javascript" src="js/eventTools.js"> function $(id){ return document.getElementById(id); } //事件委托: //把本该属于某个DOM对象的事件,委托给它的父(级)元素。 window.onload = ...
  • 生活中的例子:  我家里有三个孩子,其中两个是我自己亲生的孩子,另个一个是我朋友由于出差而把他的孩子放在我家。  我朋友的孩子就是宿主(寄生)孩子 ... 我的孩子就是我自己的孩子。...即对象不是JavaScript...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 491
精华内容 196
关键字:

原生js面试题