为您推荐:
精华内容
最热下载
问答
  • JS、ES6es6的新特性 const let 模板字符串 箭头函数 函数的参数默认值 对象和数组解构 for...of 和 for...in 怎么用es5实现promise Promise是ES6才引入的一个东西,他是一种异步编程的解决方案 if有...

    JS、ES6篇

    es6的新特性

    • const let
    • 模板字符串
    • 箭头函数
    • 函数的参数默认值
    • 对象和数组解构
    • for...of 和 for...in(for in更适合遍历对象,for of更适合遍历数组)

    怎么用es5实现promise

    Promise是ES6才引入的一个东西,他是一种异步编程的解决方案

    if有作用域吗

    只有函数有作用域,if是没有作用域的。

    但是有一种情况会让if看上去有作用域,就是在if {}语句中,使用const、let,他们会有块级作用域。(因为const、let才拥有块级作用域 )

    原型链和作用域链的区别

    (1)原型链
    当访问一个对象的某个属性时,会先在这个对象本身的属性上找,如果没有找到,会去这个属性的__proto__属性上找,即这个构造函数的prototype,如果还没找到,就会继续在__proto__上查找,
    直到最顶层,找不到即为undefined。这样一层一层往上找,彷佛是一条链子串起来,所以叫做原型链。

    (2)作用域链
    变量取值会到创建这个变量的函数的作用域中取值,如果找不到,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。

    (3)区别
    作用域是对变量而言,原型链是对于对象的属性而言
    作用域链的顶层是window,原型链的顶层是Object

    js判断类型

    1、typeof
    检测不出null 和 数组,结果都为object,所以typeof常用于检测基本类型

    2、instanceof
    不能检测出number、boolean、string、undefined、null、symbol类型,所以instancof常用于检测复杂类型以及级成关系

    3、constructor
    null、undefined没有construstor方法,因此constructor不能判断undefined和null。
    但是contructor的指向是可以被改变,所以不安全

    4、Object.prototype.toString.call
    全类型都可以判断

    数据类型怎么检测

    1、typeof
    例:console.log(typeof true) // boolean

    2、instanceof
    例:console.log([1,2] instanceof Array) // true

    3、constructor
    例: console.log([1, 2].constructor === Array) // ture

    4、Object.prototype.toString.call
    例:Object.prototype.toString.call([1, 2]) // [object Array]

    普通函数和箭头函数的区别

    1、普通函数
    可以通过bind、call、apply改变this指向
    可以使用new

    2、箭头函数
    本身没有this指向,
    它的this在定义的时候继承自外层第一个普通函数的this
    被继承的普通函数的this指向改变,箭头函数的this指向会跟着改变
    箭头函数外层没有普通函数时,this指向window
    不能通过bind、call、apply改变this指向
    使用new调用箭头函数会报错,因为箭头函数没有constructor

    如何用原生js给一个按钮绑定两个onclick事件?

    var btn = document.getElementById('btn')
    btn.addEventListener('click', fn1)
    btn.addEventListener('click', fn2)
    
    function fn1 () {
      console.log('我是方法1')  
    }
    
    function fn2 () {
      console.log('我是方法2')  
    }

    document.write和innerHTML的区别

    document.write 将内容写入页面,清空替换掉原来的内容,会导致重绘

    document.innerHTML 将内容写入某个Dom节点不会重绘

    栈和堆的区别

    1、堆
    动态分配内存,内存大小不一,也不会自动释放

    2、栈
    自动分配相对固定大小的内存空间,并由系统自动释放

    3、基本类型都是存储在栈中,每种类型的数据占用的空间的大小是确定的,并由系统自动分配和释放。内存可以及时回收。

    4、引用类型的数据都是存储在堆中。准确说是栈中会存储这些数据的地址指针,并指向堆中的具体数据。

    总的来说:里面存放的是基本数据类型(num string boolen null undefined),栈里面放的是引用数据类型(数组和对象)

     打个比方

    [注] 栈内存入的是arr 是一个地址 堆内存入的是基本数据类型 

    undefined 和 null 区别

    1、null
    什么都没有,表示一个空对象引用(主动释放一个变量引用的兑现那个,表示一个变量不再指向任何引用地址)
    2、undefined
    没有设置值的变量,会自动赋值undefined
    3、区别
    typeof undefined             // undefined
    typeof null                  // object
    null === undefined           // false
    null == undefined            // true

    eval()的作用

    eval(string) 函数计算 JavaScript 字符串,并把它作为脚本代码来执行

    如果参数是一个表达式,eval() 函数将执行表达式;

    如果参数是Javascript语句,eval()将执行 Javascript 语句;

    如果执行结果是一个值就返回,不是就返回undefined,如果参数不是一个字符串,则直接返回该参数。

    特殊:eval("{b:2}") // 声明一个对象

            eval("({b:2})") // 返回对象{b:2}

    JS哪些操作会造成内存泄露

    内存泄漏是指一块被分配的内存既不能使用,也不能回收,直到浏览器进程结束。
    1、意外的全局变量
    2、闭包
    3、没有清理的dom元素
    dom元素赋值给变量,又通过removeChild移除dom元素。但是dom元素的引用还在内存中
    4、被遗忘的定时器或者回调

    谈谈垃圾回收机制方式及内存管理

    JavaScript 在定义变量时就完成了内存分配。当不在使用变量了就会被回收,因为其开销比较大,垃圾收集器会定期(周期性)找出那些不再继续使用的变量,然后释放其内存。
    (1)垃圾回收
    标记清除法
    当变量进入环境时,将这个变量标记为'进入环境'。当标记离开环境时,标记为‘离开环境’。离开环境的变量会被回收
    引用技计数法
    跟踪记录每个值被引用的次数,如果没有被引用,就会回收
    (2)内存管理
    内存分配=》内存使用=》内存回收

    什么是闭包,如何使用它,为什么要使用它?

    (1)闭包就是能够读取其它函数内部变量的函数
    (2)使用方法:在一个函数内部创建另一个函数
    (3)最大用处有两个:读取其他函数的变量值,让这些变量始终保存在内存中
    (4)缺点:会引起内存泄漏(引用无法被销毁,一直存在)

    请解释JSONP的工作原理,以及它为什么不是真正的AJAX

    JSONP 是一种非正式传输协议,允许用户传递一个callback给服务端,然后服务端返回数据时会将这个callback 参数作为函数名来包裹住 JSON 数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
    当GET请求从后台页面返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用后台页面中的一个callback函数。
    它们的实质不同
    ajax的核心是通过xmlHttpRequest获取非本页内容
    jsonp的核心是动态添加script标签调用服务器提供的js脚本
    jsonp只支持get请求,ajax支持get和post请求

    请解释一下JavaScript的同源策略

    同源指协议,域名,端口相同,
    同源策略是一种安全协议,指一段脚本只能读取来自同一来源的窗口和文档的属性。

    关于JS事件冒泡与JS事件代理(事件委托)

    (1)事件冒泡
    当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window,过程就像冒泡泡 。如果在某一层想要中止冒泡,使用 event.stopPropagation() 。
    但是当大量标签大量事件的时候先然不可能为每个元素都加上事件,(事件绑定占用事件,浏览器要跟踪每个事件,占用更多内存。而且并不是所有事件都会被用户使用到)。所以需要事件委托来解决这个问题。
    (2)事件委托
    将事件给最外层的元素,自己不实现逻辑,由最外层元素来代理。(判断事件源,做不同处理)

    new操作符到底做了什么

    (1)var obj = new Fun()// 做了三件事

    var obj  = {}  // 创建一个空对象
    obj.__proto__ = Fun.prototype //空对象的__proto__指向构造函数的原型对象
    Fun.call(obj) // 构造函数this指向替换成obj

    (2)实现一个new
    function _new(fn, ...arg) {
        const obj = Object.create(fn.prototype);
        const ret = fn.apply(obj, arg);
        // 根据规范,返回 null 和 undefined 不处理,依然返回obj,不能使用
        // typeof result === 'object' ? result : obj
        return ret instanceof Object ? ret : obj;
    }

    js延迟加载的方式有哪些?

    (1)defer属性
            <script src="test.js" defer="defer"></script>
            立即下载,但是会等到整个页面都解析完成之后再执行
    (2)async属性
            <script src="test.js" async></script>
            不让页面等待脚本下载和执行(异步下载),但是无法控制加载的顺序
    (3)动态创建script标签
    (4)使用定时器延迟
    (5)让js最后加载

    promise、async有什么区别

    1、什么是Async/Await
    async/await是写异步代码的新方式,使用的方式看起来像同步
    async/await是基于Promise实现的,它不能用于普通的回调函数。

    2、什么是promise
    为了解决异步嵌套而产生,让代码更易于理解

    区别,async/await让代码更像同步,进一步优化了代码

    == 和 ===的区别,什么情况下用相等==

    ”==” 是判断转换后的值是否相等, 

    ”===” 是判断值及类型是否完全相等

    不需要判断类型时可以使用==

    bind、call、apply的区别

    let o1 = {
        a: 1
    };
    let o2 = {
        a: 2
    };
    let o3 = {
        a: 3
    };

    function fn(b, c) {
        console.log(this.a + b + c);
    };

    1、bind
    var c = b.bind(o1, 2, 3); // 返回一个已经切换this指向的新函数
    c(1,1)//依旧是6 因为bind指定this后不会再改变

    2、apply
    b.apply(a, [1, 1])  // 将b添加到a环境中
    第一个参数是this指向的新环境
    第二个参数是要传递给新环境的参数
    注意: 第一个参数为null时表示指向window

    3、call
    b.call(a, 1, 1) // 将b添加到a环境中
    第一个参数是this指向的新环境
    第二、三...个参数是传递给新环境的参数
    注意: 第一个参数为null时表示指向window

    小结: bind方法可以让函数想什么时候调用就什么时候调用。apply、call方法只是临时改变了this指向。

    call、apply区别

    相同点:都是重定向this指针的方法。
    不同点:call和apply的第二个参数不相同,call是若干个参数的列表。apply是一个数组

    let mock = { value : 1 };
    function mockNum(){
     console.log('value',this.value)
    }
    mockNum.call(mock) // 改变了函数中this的指向,当前this指向了mock对象
    
    //转换一下实现方法就是
    
    let mock = {
      value:1;
      mockNum:function(){
         console.log('value',this.value)
      }
    }
    mock.mockNum();
    //所以经过上面这个操作的演化而来的结果就是如下步骤:
    //1. 将函数设为一个对象的属性
    //2. 并将这个函数的属性调用
    //3. 删除该函数
    
    Function.prototype.Mycall = function(context){
      let obj = context || window;
      obj.fn = this; //   这一步可以看做是this其实就指的当前函数。
      let args = [...arguments].slice(1); // 返回删除第一个元素的数组;
      let result = obj.fn(...args); // 调用函数
      delete obj.fn;
      return result;
    }
    
    // 操作一下
    let mock = { value : 1 };
    function mockNum(){
      console.log('value',this.value);
    }
    mockNum.Mycall(mock) // value 1
    
    
    
    //apply的写法
    Function.prototype.Myapply = function (context){
        let obj = context || window;
        obj.fn = this;
        let result = arguments[1] ? obj.fn(arguments[1]) : obj.fn([]);
        delete obj.fn;
        return result;
    }
    let mock3 = {
      arr: [1, 2, 3, 4, 5],
    };
    function arrx2(arr) {
      return this.arr.concat(arr).map((x) => x * 2);
    }
    console.log("arrx2", arrx2.myApply(mock3));

    介绍暂时性死区

    在代码块内,使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。

    两个对象如何比较

    有思路即可,步骤:
    (1)判断两个类型是否对象
    (2)判断两个对象key的长度是否一致
    (3)判断属性value值的数据类型,根据不同数据类型做比较
        a、是对象,重复这个步骤
        b、是数组,转字符串比较
        c、是基本类型,直接判断

    介绍各种异步方案

    (1)回调函数
    (2)promise
    (3)async/await

    Promise和Async处理失败的时候有什么区别

    (1)Promise错误可以在构造体里面被捕获,而async/await返回的是promise,可以通过  catch直接捕获错误。
    (2)await 后接的Promise.reject都必须被捕获,否则会中断执行

    JS为什么要区分微任务和宏任务

    (1)js是单线程的,但是分同步异步
    (2)微任务和宏任务皆为异步任务,它们都属于一个队列
    (3)宏任务一般是:script,setTimeout,setInterval、setImmediate
    (4)微任务:原生Promise
    (5)遇到微任务,先执行微任务,执行完后如果没有微任务,就执行下一个宏任务,如果有微任务,就按顺序一个一个执行微任务

    Promise和setTimeout执行先后的区别

    Promise是微任务,setTimeout是宏任务,先执行微任务,如有还有微任务执行完微任务再执行下一个宏任务

    添加原生事件不移除为什么会内存泄露

    setTimeout(0)和setTimeout(1)之间的区别

    定时器表面意思是过指定时间后执行,但是真正的含义是每过指定时间后,会有fn进入事件队列
    (1)setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,意思就是不用再等多少秒了,只要主线程执行栈内的同步任务全部执行完成,栈为空就马上执行
    (2)setTimeout(fn,1) 1毫秒后执行,但是因为要先执行前面的宏任务,所以不一定就是在一毫秒后执行,取决于队列里任务执行的速度

    for..in 和 object.keys的区别

    Object.keys不会遍历继承的原型属性
    for...in 会遍历继承的原型属性

    XML和JSON的区别?

    1.xml是重量级的,json是轻量级的。
    2.xml在传输过程中比较占带宽,json占带宽少,易于压缩。
    3.xml和json都用在项目交互下,xml多用于做配置文件,json用于数据交互。

    说说你对AMD和Commonjs的理解

    两者都是为了实现模块化编程而出现的
    (1)commonjs
    通常被应用于服务器,在服务器端,模块的加载和执行都在本地完成,因此,CommonJS并不要求模块加载的异步化。
    核心思想:xsdz独文件就是一个模块,通过require方法来同步加载要依赖的模块,然后通过extports或则module.exports来导出需要暴露的接口。
    (2)AMD
    可以实现异步加载依赖模块,预加载,在并行加载js文件同时,还会解析执行该模块。虽然可以并行加载,异步处理,但是加载顺序不一定
    (3)CMD
    懒加载,虽然会一开始就并行加载js文件,但是不会执行,而是在需要的时候才执行。

    js的涉及模式

    单例模式、策略模式、代理模式、迭代器模式...等等

    ["1", "2", "3"].map(parseInt) 答案是多少?

    (1)map用法:
    arr.map(function(el, index, arr) {
        return el
    })
    map方法接收一个函数参数,并且这个函数可以接收三个参数
    el:遍历过程中的当前项,
    index:遍历过程中的当前下标
    arr: 原数组

    (2)parseInt用法:
    parseInt(str, num)
    根据num解析str,并返回一个整数。
    str: 要解析的字符串,如果字符第一个数不能被转换,返回NaN。
    num: 基数,介于 2 ~ 36 之间,如果传0,则默认用10计算。num不在区间内,返回NaN

    (3)所以这道题,关键点就在num
    el和index 相当于 str 和 num 带入一下
    parseInt('1', 0) // '1' 用基数10算 为1
    parseInt('2', 1) // NaN 1不在2-36内
    parseInt('3', 2) // NaN  2进制内没有超过1的存在

    常见兼容性问题?

    (1)事件对象兼容
            e  = e || window.event;
    (2)阻止事件冒泡兼容
            event.stopPropagation? event.stopPropagation():event.cancelBubble=true;
    (3)阻止默认行为兼容
            evt.preventDefault?evt.preventDefault():evt.returnValue=false;
    (4)事件监听兼容
            addEventListener  ? addEventListener  : attachEvent()
            removeEventListener() ? removeEventListener() : detachEvent()
    (5)事件目标对象兼容
            var src = event.target || event.srcElement;

    说说你对promise的了解

    (1)promise是为解决异步处理回调金字塔问题而产生的
    (2)有三种状态,pengding、resolve、reject,状态一旦决定就不会改变
    (3)then接收resolve(),catch接收reject()

    介绍js有哪些内置对象?

    String对象、Array对象、Object对象、Number对象
    Math对象、Date对象、Boolean对象

    说几条写JavaScript的基本规范?

    1、不要在同一行声明多个变量
    2、使用 === 和 !== 来比较
    3、不要使用全局函数
    4、变量在使用之前的位置声明(减少变量提升干扰)
    5、if用花括号包起来即使只有一行
    6、写注释

    JavaScript有几种类型的值?,你能画一下他们的内存图吗?

    栈:原始数据类型(Undefined  Null  Boolean  Number  String)
    堆:引用数据类型(对象、数组、函数)

    href="#"与href="javascript:void(0)的区别"?

    1、# 包含了一个位置信息,默认的锚是#top 也就是网页的上端。在页面很长的时候会使用 # 来定位页面的具体位置,格式为:# + id。

    2、javascript:void(0), 仅仅表示一个死链接。

    如果你要定义一个死链接请使用 javascript:void(0) 

    对this的理解

    1、单独使用,this表示全局对象
    2、在函数中,this表示全局对象
    3、在对象的一个函数方法中,this表示这个对象
    4、可以通过apply、bind来更改this的指向

    ps: this永远指向的是最后调用它的对象,仅当它在对象的一个函数方法中时会有差异

    promise.all 返回什么

    如果没有报错,返回执行结果[res1, res2,...]
    如果报错,则返回第一个报错的promise的结果

    多个await的执行顺序,如果要同步执行如何实现?

    使用Promise.all
    promise.all是等所有异步操作都完成之后返回结果,相当于让这些异步同步了

     拖拽会用到哪些事件

    • dragstart:拖拽开始时在被拖拽元素上触发此事件,监听器需要设置拖拽所需数据,从操作系统拖拽文件到浏览器时不触发此事件.
    • dragenter:拖拽鼠标进入元素时在该元素上触发,用于给拖放元素设置视觉反馈,如高亮
    • dragover:拖拽时鼠标在目标元素上移动时触发.监听器通过阻止浏览器默认行为设置元素为可拖放元素.
    • dragleave:拖拽时鼠标移出目标元素时在目标元素上触发.此时监听器可以取消掉前面设置的视觉效果.
    • drag:拖拽期间在被拖拽元素上连续触发
    • drop:鼠标在拖放目标上释放时,在拖放目标上触发.此时监听器需要收集数据并且执行所需操作.如果是从操作系统拖放文件到浏览器,需要取消浏览器默认行为.
    • dragend:鼠标在拖放目标上释放时,在拖拽元素上触发.将元素从浏览器拖放到操作系统时不会触发此事件. 

    请列举jquery中的选择器

    #id,.class,element,:first,:even,:eq(index),:contains(text)

    注:这些选择器都是基于$()的

    Javascript中的定时器有哪些?他们的区别及用法是什么?

    setTimeout 只执行一次
    setInterval 会一直重复执行

    请描述一下 cookies sessionStorage和localstorage区别

    编写一个方法去掉数组里面重复的内容

    var arr=['abc','abcd','sss','2','d','t','2','ss','f','22','d']
    //定义一个新的数组
    var s=[]
    //遍历数组
    for(var i=0;i<arr.length;i++){
            if(s.indexOf(arr[i]) == -1){
                //判断在s数组中是否存在,不存在则push到s数组 
                //-1是不存在 1是存在
                s.push(arr[i])中
            }
    }
    console.log(s)
    //输出结果:["abc","abcd","sss","2","d","t","ss","f","22"]

    什么是ajax? ajax的步骤?

    ajax(异步javascript xml) 能够刷新局部网页数据而不是重新加载整个网页。
    如何使用ajax?
    第一步,创建xmlhttprequest对象

    var xmlhttp =new XMLHttpRequest();
    //XMLHttpRequest对象用来和服务器交换数据。
    var xhttp;
    if (window.XMLHttpRequest) {
    //现代主流浏览器
    xhttp = new XMLHttpRequest();
    } else {
    // 针对浏览器,比如IE5或IE6
    xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }

    第二步,使用xmlhttprequest对象的open()和send()方法发送资源请求给服务器。
    第三步,使用xmlhttprequest对象的responseText或responseXML属性获得服务器的响应。
    第四步,onreadystatechange函数,当发送请求到服务器,我们想要服务器响应执行一些功能就需要使用onreadystatechange函数,每次xmlhttprequest对象的readyState发生改变都会触发onreadystatechange函数。

    http和https有何区别?

    http是HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。
    https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,
    加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。
    此外客户端可以验证服务器端的身份,如果配置了客户端验证,服务器方也可以验证客户端的身份。

    常见的HTTP状态码 

    2开头 (请求成功)表示成功处理了请求的状态代码。
    200   (成功)  服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
    201   (已创建)  请求成功并且服务器创建了新的资源。
    202   (已接受)  服务器已接受请求,但尚未处理。
    203   (非授权信息)  服务器已成功处理了请求,但返回的信息可能来自另一来源。
    204   (无内容)  服务器成功处理了请求,但没有返回任何内容。
    205   (重置内容) 服务器成功处理了请求,但没有返回任何内容。
    206   (部分内容)  服务器成功处理了部分 GET 请求。


    3开头 (请求被重定向)表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
    300   (多种选择)  针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
    301   (永久移动)  请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
    302   (临时移动)  服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
    303   (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
    304   (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
    305   (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
    307   (临时重定向)  服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。


    4开头 (请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理。
    400   (错误请求) 服务器不理解请求的语法。
    401   (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
    403   (禁止) 服务器拒绝请求。
    404   (未找到) 服务器找不到请求的网页。
    405   (方法禁用) 禁用请求中指定的方法。
    406   (不接受) 无法使用请求的内容特性响应请求的网页。
    407   (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
    408   (请求超时)  服务器等候请求时发生超时。
    409   (冲突)  服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
    410   (已删除)  如果请求的资源已永久删除,服务器就会返回此响应。
    411   (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。
    412   (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。
    413   (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
    414   (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
    415   (不支持的媒体类型) 请求的格式不受请求页面的支持。
    416   (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。
    417   (未满足期望值) 服务器未满足"期望"请求标头字段的要求。


    5开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
    500   (服务器内部错误)  服务器遇到错误,无法完成请求。
    501   (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
    502   (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
    503   (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
    504   (网关超时)  服务器作为网关或代理,但是没有及时从上游服务器收到请求。
    505   (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。

    如何进行网站性能优化

    (1)目的: 从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。从服务商角度而言,优化能够减少页面请求数、或者减小请求所占带宽,能够节省可观的资源。

    (2)措施:

    ——减少HTTP请求数。
    ——使用缓存。
    ——脚本的无阻塞加载。
    ——内联脚本的位置优化等。
    ——Javascript中的DOM 操作优化、CSS选择符优化。
    ——图片编码优化,懒加载。
    ——使用负载均衡方案。

    什么是mvvm,mvc?区别?

    MVC(Model-View-Controller)

    MVC是比较直观的架构模式,用户操作
     ->View(负责接收用户的输入操作)
     ->Controller(业务逻辑处理)->Model(数据持久化)->View(将结果反馈给View)。             MVC使用非常广泛,比如JavaEE中的SSH框架。

    MVVM(Model-View-ViewModel)

    ->Model:数据层

    ->View:视图层

    ->ViewModel:数据视觉层

    px和em的区别

    px表示像素 (计算机屏幕上的一个点:1px = 1/96in),是绝对单位,不会因为其他元素的尺寸变化而变化;
    em表示相对于父元素的字体大小。em是相对单位 ,没有一个固定的度量值,而是由其他元素尺寸来决定的相对值。

    优雅降级和渐进增强

    渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
    优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。

    其实渐进增强和优雅降级并非什么新概念,只是旧的概念换了一个新的说法。在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容。

    怎样添加、移除、移动、复制、创建和查找节点?

    (1)创建新节点

    createDocumentFragment() //创建一个DOM片段

    createElement() //创建一个具体的元素

    createTextNode() //创建一个文本节点

    (2)添加、移除、替换、插入

    appendChild() //添加

    removeChild() //移除

    replaceChild() //替换

    insertBefore() //插入

    (3)查找

    getElementsByTagName() //通过标签名称

    getElementsByName() //通过元素的Name属性的值

    getElementById() //通过元素Id,唯一性

    浏览器是如何渲染页面的?

    1.解析HTML文件,创建DOM树。
      自上而下,遇到任何样式(link、style)与脚本(script)都会阻塞(外部样式不阻塞后续外部脚本的加载)。
    2.解析CSS。优先级:浏览器默认设置<用户设置<外部样式<内联样式

    从输入url到显示页面,都经历了什么?

    1、首先,在浏览器地址栏中输入url。
    2、浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
    3、在发送http请求前,需要域名解析(DNS解析)(DNS(域名系统,Domain Name System)是互联网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住IP地址。),解析获取相应的IP地址。
    4、浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。(TCP即传输控制协议。TCP连接是互联网连接协议集的一种。)
    5、握手成功后,浏览器向服务器发送http请求,请求数据包。
    6、服务器处理收到的请求,将数据返回至浏览器。
    7、浏览器收到HTTP响应。
    8、读取页面内容,浏览器渲染,解析html源码。
    9、生成Dom树、解析css样式、js交互。
    10、客户端和服务器交互。
    11、ajax查询。

    JavaScript中如何检测一个变量是一个String类型?请写出函数实现

    typeof(obj) === "string"
    typeof obj === "string"
    obj.constructor === String

    判断一个字符串中出现次数最多的字符,统计这个次数

        function aa() {
            let str = 'asdfssaaasasasasaa';
            let json = {};
            for (let i = 0; i < str.length; i++) {
                let index = str[i]
                if (!json[index]) {
                    json[index] = 1
                } else {
                    json[index]++
                }
            }
            let iMax = 0
            let iIndex = ''
            for(let k in json){
                if(json[k]>iMax){
                    iMax =json[k]
                    iIndex=k
                }
            }
            console.log('出现次数最多的是:' + iIndex + '出现' + iMax + '次');

    $(document).ready()方法和window.onload有什么区别?

    (1)、window.onload方法是在网页中所有的元素(包括元素的所有关联文件)完全加载到浏览器后才执行的。
    (2)、$(document).ready() 方法可以在DOM载入就绪时就对其进行操纵,并调用执行绑定的函数。

    window.onLoad和DOMContentLoaded事件的先后顺序?

    顺序

    一般情况下,DOMContentLoaded事件要在window.onload之前执行,当DOM树构建完成的时候就会执行 DOMContentLoaded事件,而window.onload是在页面载入完成的时候,才执行

    区别

    1、当 onload事件触发时,页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了。

    2、当DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片,flash。

    JavaScript中的变量声明提升?

    函数声明和变量声明总是被JavaScript解释器隐式地提升到包含他们的作用域的最顶端。

    function优先声明于var。

    函数表达式中只会提升名称,函数体只有在执行到赋值语句时才会被赋值。

    function foo() {
         bar(); 
         var x = 1; 
    } 
    function foo() {//等同于
       var x;
       bar(); 
       x = 1; 
    } 
    function test() { 
        foo(); // TypeError "foo is not a function" 
        bar(); // "this will run!"
        var foo = function () {}// 函数表达式被赋值给变量'foo' 
        function bar() {}// 名为'bar'的函数声明 
    }

    请写出console.log中的内容

        var msg = 'hello';//顶级作用域window下有个变量msg
        function great(name, attr) {
            var name = 'david';
            var greating = msg + name + '!';
            var msg = '你好';
            for (var i = 0; i < 10; i++) {
                var next = msg + '你的id是' + i * 2 + i;
            }
            console.log(arguments[0]);//david
            console.log(arguments[1]);//undefind
            console.log(greating);//undefineddavid!
            console.log(next);//你好你的id是189
        }
    
        great('Tom')

    注:在作用域内会先调用作用域内的变量,如果var变量在声明之前就使用了就是变量提升是undefined

    JS延迟加载的方式有哪些?

    1、 JS的延迟加载有助与提高页面的加载速度。

    2、 defer 和async 、动态创建DOM 方式(用得最多)、按需异步载入

    3、 JSdefer:延迟脚本。立即下载,但延迟执行(延迟到整个页面都解析完毕后再运行),按照脚本出现的先后顺序执行。

    4、 async :异步脚本。下载完立即执行,但不保证按照脚本出现的先后顺序执行。

    为什么避免v-if和v-for一起使用

    当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级;
    可以先对数据在计算数据中进行过滤,然后再进行遍历渲染;
    操作和实现起来都没有什么问题,页面也会正常展示。但是会带来不必要的性能消耗;

    深拷贝和浅拷贝的方法

    浅拷贝  Object.assign()    //es6的方法

    var obj={aa:1,b:{item:'45'}};
    var newObj=Object.assign({},obj);
    obj.aa=2;
    obj.b.item='kk';
    console.log(newObj.aa);        //1
    console.log(newObj.b.item);    //kk

    深拷贝  JSON.parse(JSON.stringify(obj))

      function cloneDeep(source) {
          if (!isObject(source)) return source; // 非对象返回自身
          var target = Array.isArray(source) ? [] : {};
          for (var key in source) {
            if (source.hasOwnProperty(i)) {
              if (isObject(source[key])) {
                target[key] = cloneDeep(source[key]); // 注意这里
              } else {
                target[key] = source[key];
              }
            }
          }
          return target;
        }
        function isObject(obj) {
          return typeof obj === 'object' && obj != null;
        }

    如何统计网⻚上出现了多少种标签 

    获取所有的DOM节点

    document.querySelectorAll('*')

    NodeList集合转化为数组

    [...document.querySelectorAll('*')]

    获取数组每个元素的标签名 

    [...document.querySelectorAll('*')}.map(ele => ele.tagName)
    

    去重

    new Set([...document.querySelectorAll('*').map(ele=>ele.tagName)).size
    展开全文
    m0_45159572 2021-09-02 13:57:55
  • var关键字是原生JS中声明变量的关键字,let关键字是ES6语法中新增关键字 let关键字声明的变量不能重复声明,var关键字可以重复声明变量 let关键字解析变量时没有预解析,var关键字声明的变量包含预解析过程 let...

    一、简答题

    1. 简述git fetch命令和git pull命令的区别,它们都在什么情况下使用?

    git fetch 是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。 而 git pull 则是将远程主机的最新内容拉下来后直接合并,即: git pull = git fetch + git merge ,这样可能会产生冲突,需要手动解决。
    fetch命令和pull命令都是从远程仓库拉取更新的命令
    fetch命令直接从远程仓库拉取指定分支的更新到本地对应的分支
    pull命令从远程仓库拉取指定的分支更新到本地并合并到当前分支,相当于fetch+merge命令的结合使用

    3. 简述git中常用的操作命令

    git config --global user.name “”
    git config --global user.email “”
    git init
    git status
    git add
    git commit
    git push
    git pull
    git fetch
    git log
    git reset

    4. ES6中的let关键字和var关键字声明变量的区别?

    var关键字是原生JS中声明变量的关键字,let关键字是ES6语法中新增关键字
    let关键字声明的变量不能重复声明,var关键字可以重复声明变量
    let关键字解析变量时没有预解析,var关键字声明的变量包含预解析过程
    let关键字提供了块级作用域,var关键字没有块作用域只有局部/全部作用域

    5. 简述模板字符串的使用优势?

    常规字符串中如果需要进行字符串和变量数据的拼接,需要通过连接符号+进行拼接,如果字符串和拼接的变量数量较多,拼接过程非常繁琐,代码阅读非常不便利
    模板字符串是ES6新增的语法,使用反引号包含一串字符,变量可以通过固定语法${}的形式在字符串内部直接使用和操作,相当于提升了操作效率

    6. ES6新语法中对数组进行了那些改进?

    ES6语法中针对数组的创建和其他类数组的转换提供了两个常用的函数
    Array.of()用于新建数组对象
    Array.from()用于将其他类数组转换成数组

    7. 简述ES6中数组解构赋值都有哪几种操作方式?

    解构赋值的操作,数组的解构主要包含如下几种

    • 完全解构
    • 不完全解构
    • 解构失败 | 过度解构
    • 解构默认值
    • 缺省解构

    8. 简述你对ES6中对象解构赋值的认识?

    ES6中提供的对象解构语法包含如下几种

    • 完全解构
    • 简洁语法解构
    • 不完全解构,是代码中使用最频繁的操作

    9. let {toString: f} = 100,请描述f的值是什么?为什么?

    f打印出来是一个函数
    100是一个数值类型,本质上是一个Number对象,对象包含toString()函数用于输出数据,解构赋值中将Number对象中的toString进行了解构,所以解构中赋值的变量f中存储的就是一个toString函数声明

    二、实操题

    1. 将数组[100, 200, [101, 201], [301, 302]]的值,赋值给变量

    let arr = [100, 200, [101, 201], [301, 302]]
    let [a, b, [c, d], [e, f]] = arr
    // a=100, b=200, c=101, d=201, e=301, f=302

    2. 观察代码说明输出结果

    let obj = {a: 1, b: 2, c: {d: {e: 5}}}
    let {a, b, c: {d}} = obj
    console.log(d) // ① ? {e: 5} 注意这里按照数据的结构进行取值,展示d变量中的数据
    /** 解构默认值 **/
    let {a = 10, b = 5} = {a: 3};
    console.log(a, b) // ② ?
    // a-3 b-5 解构默认值~如果解构得到数据就直接使用,没有数据使用默认值数据
    let {a: aa = 10, b: bb = 5} = {a: 3};
    console.log(aa, bb) // ③ ? aa-3 bb-5 解构默认值操作原理
    let obj = {p: [{y: ‘world’}] };
    let {p: [{ y }, x ] } = obj;
    console.log(x, y) // ④ ? undefined world

    3. 观察代码,说明输出结果

    const userStr = “zhangsan,lisi,wangwu,zhaoliu”;
    const { 1: a, 3: b } = userStr.split(’,’);
    console.log(a, b) // ? list zhaoliu
    上述代码中,通过split()函数将字符串拆分成了数组
    然后通过解构赋值的方式进行了数据的提取,通过对象的结构提取数组中的数据
    上述代码中如果不会出现错误的情况下,可以按照索引进行解构
    a中解构的数据list,b中解构的数据zhaoliu

    展开全文
    qq_45272615 2021-10-24 12:40:40
  • …} C、function fct(name=“defeult”) {…} D、let fct = (name=“default”)=> {…} ACD A-原生JS中默认值的添加 B-数据覆盖,不是默认值 C-ES6语法中给形式参数添加默认值 D-箭头函数中使用ES6语法的默认值 10、...

    一、多选题

    1、关于剩余参数的使用,正确的是?AB
    A、function fn(name, …args) {…}
    B、function fn(…args) {…}
    C、function fn(…args, name) {…}
    D、function fn(…name, …args) {…}
    答案:AB
    C问题:剩余参数只能出现在参数列表的最后一个位置
    D问题:函数的参数中,剩余参数只能有一个

    2、声明类型的语法,正确的是?BC
    A、class Person() {}
    B、class Person {}
    C、function Person () {}
    D、function Person {}
    答案:BC
    A问题,class语法中没有类型名称后面的括号
    D问题,function语法中,类型名称后面包含一个括号,使用函数模拟的类型

    3、关于ES6中constructor()的描述,正确的是?
    A、类型中的构造函数,用来在创建对象的同时初始化对象属性
    B、创建指定类型的对象时,会自动调用执行
    C、类型中的构造函数,需要手工调用执行
    D、类型中的普通函数,需要手工调用执行
    答案:ABD
    C问题:构造函数是创建对象的时候自动执行,不需要手工调用

    4、箭头函数的使用,操作语法正确的是?
    A、let fn = ()-> console.log(“hello”)
    B、let fn = ()=> console.log(“hello”)
    C、let fn = name -> console.log(“params”)
    D、let fn = name => console.log(“params”)
    答案:BD
    AC问题:箭头函数中使用错误了箭头符号

    5、箭头函数中的参数的使用,正确的是?
    A、let func = name, age => console.log(名称:${name}, 年龄:${age})
    B、let func = (name, age) => console.log(名称:${name}, 年龄:${age})
    C、let func = name, age => {console.log(名称:${name}, 年龄:${age})}
    D、let func = (name, age) => {console.log(名称:${name}, 年龄:${age})}
    答案:BD
    AC问题:多个参数出现时,不能省略括号

    6、箭头函数中返回值的操作,正确的是?
    A、let fc = (x, y) => {x++; y++; return x + y;}
    B、let fc = (x, y) => {x++; y++; x + y;}
    C、let fc = (x, y) => return x + y
    D、let fc = (x, y) => x + y
    答案:AD
    B问题:函数代码部分,带有花括号的情况下需要通过return才能返回数据
    C问题:函数代码部分,省略花括号的情况下不需要添加return关键词可以直接返回数据

    7、关于类和对象的描述,正确的是?
    A、类表示类型的意思
    B、对象是包含数据的、实际存在的物体
    C、一个类型只能创建一个对象
    D、多个对象可以属于一个类型
    ABD
    C问题:一个类型可以创建多个互相独立的对象

    8、ES6类型中,对于静态属性和静态函数的操作正确的是?
    A、静态属性是声明在类型内部、类型方法外部的、使用let声明的变量
    B、静态属性是声明在类型内部、类型方法外部的、使用static声明的变量
    C、静态属性是属于类型的属性,所以只能被类型名称调用
    D、静态属性是属于类型的属性,所以可以被类型名称和该类型创建的所有对象调用
    BC

    9、关于函数中使用默认值,操作方式正确的是?
    A、function fct(name) { name = name || ‘default’;… }
    B、function fct(name) {name = “default”;…}
    C、function fct(name=“defeult”) {…}
    D、let fct = (name=“default”)=> {…}
    ACD
    A-原生JS中默认值的添加
    B-数据覆盖,不是默认值
    C-ES6语法中给形式参数添加默认值
    D-箭头函数中使用ES6语法的默认值

    10、面向对象的继承关系中,正确的操作语法是?
    A、class Student extends Person {…}
    B、class Student(Person) {…}
    C、class Student extends Person() {…}
    D、class Student extends Person, Job {…}
    A
    B问题:继承语法,不是类型后面添加括号的语法
    C问题:继承的父类不能添加括号
    D问题:JS中的继承是单继承机制,不能同时继承多个类型

    二、简答题

    1、观察下面的代码,最终控制台会输出什么结果呢?请说明原因?

    let name = "TOM"
    function fn() {
    console.log(name)   // ? 
    let name = "JERRY"
    }
    fn()
    

    输出错误,let声明的变量存在暂时性死区,变量声明之前不能使用该变量

    2、梳理下面的代码,最终输出的数据是什么呢?请说明原因?

    let person = {'pName': 'OFFCN', 'pAge': 20, 'pGender': 'male'}
    let {pName: name, pAge} = person
    console.log(name) 	// ①
    console.log(pName)	// ② 
    console.log(pAge)	// ③
    

    ① 输出OFFCN,别名输出,给pName的值赋值到了一个名称为name的变量中
    ② 错误,一旦出现了别名赋值,原来的属性名称就不能使用
    ③ 20
    解构赋值中,如果给一个属性添加了别名,属性名称就不能再使用了,所以pName报错

    3、解析下面的代码,最终输出什么结果?为什么?

    for ( var i = 0; i < 10; i ++ ) {
    setTimeout(function() {
        console.log(i);  // ① 10, 10, 10, 10, 10, 10, 10...
    		})
    	}
    for ( let j = 0; j < 10; j ++ ) {
    setTimeout(function() {
        console.log(j);  // ②
    		})
    	}
    

    ① 10,var声明的变量的作用域只有全局和局部,for循环中多次循环使用的是同一个作用域空间,setTimeout()延时函数会在循环全部执行完成后输出,循环中最后一次判断时i=10<10跳出循环,此时最终i的值是10;
    ② 0.1.2.3…9,let声明的变量存在块级作用域,for循环每次循环都是一个独立的作用域,延时函数执行的时候相当于在10个不同的作用域中执行,最终输出了差异化的数据

    编程题
    1、公司要给员工涨薪,并重新记录到一个新的变量中,请编写代码实现

    // 公司员工数据
    let emps = [
    {name: 'Jams Gosling', job: 'Java工程师', salary: 12000},
    {name: 'Guido Van Rossum', job: 'Python工程师', salary: 11000},
    {name: 'Brendan Eich', job: 'JavaScript工程师', salary: 12500},
    {name: 'John Resig', job: '前端工程师', salary: 12800},
    {name: 'Dennis Ritchie', job: 'C工程师', salary: 9000},
    {name: 'Bjarne Stroustrup', job: 'C++工程师', salary: 10000},
    {name: 'Tim Berners Lee', job: 'WEB工程师', salary: 13000},
    {name: 'Alan Cooper', job: 'VB工程师', salary: 8000},
    {name: 'Rob Pick', job: 'Go工程师', salary: 13000}
    ]
    

    请编写代码实现员工的涨薪操作:

    var newEmps = emps.map(value=> {
        return {
    		...value,
           salary: value.salary + 1000
    		}
    	})
    console.log(newEmps) // 涨薪后的数组
    
    展开全文
    qq_45272615 2021-10-16 23:00:45
  • 前端全部面试题 https://blog.csdn.net/qq_40055200/article/details/104637574  es6面试题 1.const let var 区别? var声明变量存在变量提升,let和const不存在变量提升 let声明变量和const声明常量,两个都可以...

     前端全部面试题

    https://blog.csdn.net/qq_40055200/article/details/104637574

     es6面试题

     1.const let var 区别?

    • var声明变量存在变量提升,let和const不存在变量提升
    • let声明变量和const声明常量,两个都可以形成块级作用域
    • const 声明之后必须马上赋值,否则会报错

    • const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。

    • var是不受限于块级的,而let是受限于块级
    • ES5中是没有块级作用域的,并且var有变量提升,在let中,使用的变量一定要进行声明
    • const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错
    • var会与window相映射(会挂一个属性),而let不与window相映射

    2.变量提升:变量提升会优先声明

    变量提升意思是 var声明变量时 先声明 再赋值

    var a = 5;
    function test3(){
            var a;
            cosnole.log(a)
    }
    test3();      ------------>undefined
      
    
    var a = 5;
    function test3(){
    var a = 3;
    console.log(a)
    }
    test3()    -------------->3 (变量提升)

    函数提升:将整个代码块提升到他所在的作用域,最开始执行

    var a = 1;
    function foo() {
    var a = function(){} ----->函数提升
    a = 10;
    console.log(a)------------10
    return
    }
    foo()
    console.log(a)--------------1
    

    匿名函数不会被提升

    3.什么是匿名函数

    • 语法:(function(){...}());
    • 前面的括号包含函数体,后面的括号就是给匿名函数传递参数并立即执行之
    • 匿名函数的作用是避免全局变量的污染以及函数名的冲突
    • 小括号的作用:小括号对返回的,就是一个匿名函数的Function 对象
    (function(x,y){
    alert(x+y);
    return x+y;
    }(3,4)); 

    JS匿名函数理解 - 辉夜 - 博客园

    4.JS执行上下文

    当代码运行时,会产生一个对应的执行环境,在这个环境中,所有变量会被事先提出来(变量提升),有的直接赋值,有的为默认值 undefined,代码从上往下开始执行,就叫做执行上下文。 (代码从上往下执行的过程就是执行上下文)

    运行环境:

    • 全局执行上下文,函数上下文与eval上下文(全局环境)
    • 全局上下文指:window对象(全局环境)
    • 函数上下文:指this自己(.函数环境)
    • eval上下文:一般不会用

    5.js中this对象的指代

    • 全局环境中this指向window对象
    • 当前函数中,this指当前对象
    • 箭头函数没有this指向,this指向就箭头函数外部的函数,指向上下文

    6.如何判断一个对象是否属于某个类

    if(spear instanceof Array){console.log('yes');} 

    7.箭头函数,使用箭头函数应注意什么?

    优点:

    • 语法简洁,函数定义不再使用关键字function(),而是用()=>来进行定义
    • 解决了this指向的问题,有一个确定的作用域
    • 如果只有一个形参,可以不打小括号
    • 如果只有一条执行语句,可以不打大括号
    • 只有一条执行语句,并且需要返回这条语句的结果,可以不用写return

    注意:

    1. 箭头函数没有自己的this,它的this是继承而来,默认指向在定义它时所处的对象(宿主对象)
    2. 不能用作构造函数,这就是说不能够使用new命令,否则会抛出一个错误
    3. 不能够使用arguments对象
    4. 不可以使用yield命令,因此箭头函数不能用作 Generator 函数

    关于箭头函数中的this的指向_xu4321083的博客-CSDN博客_箭头函数中的this

    知乎

    举例子: 

    箭头函数的写法:
    // ES5
    var x = function(x, y) {
         return x * y;
    }
     
    // ES6
    const x = (x, y) => x * y;
    • 箭头函数是匿名函数的一种简写方式
    • ()内是参数,一个参数的时候可以省略
    • =>后面是返回值,省略了return
    • 词法作用域,不会绑定this;箭头函数会默认绑定外层的this的值,所以箭头函数中this的值和外层this的值是一样的
    • 如果函数部分只是一个语句,则可以省略return关键字和大括号{}
    以下两者等价
    const x = (x, y) => x * y;
     
    const x = (x, y) => { return x * y };

    8.模板字符串

    模版字符串,用`(反引号)标识,用${}将变量括起来。

    var name="zzw";
    `${name},no matter what you do,I trust you.`

    ES6模板字符串 - WhiteSpace - 博客园

    9. ... 展开运算符

    可以将数组或对象里面的值展开;还可以将多个值收集为一个变量

    数组合并的时候用

    // 数组合并
    var array1 = [1, 2, 3,4];
    var array2 = [4, 5, 6];
    var array3 = [...array1, ...array2, 7, 8]; //[1,2,3,4,4,5,6,7,8]
    array1.push(...array2 )// 当然也可以使用concat等数组合并方法,但是扩展运算符提供了一种新的方式

     向数组中添加元素

    var items = [1,2,3];
    var newArr  =  [...items,4]
    console.log(newArr); // [1,2,3,4]

    合并对象属性,和Object.assign作用是一样的;

    var obj = {name:"zs",age:12};
    var obj2 = {age:14,addr:"gz"}
    console.log({...obj,...obj2}); // {name:"zs",age:14,addr:"gz"}
    

    10.解构赋值 

    所谓的解构赋值其实就是分解出一个对象的解构,分成两个步骤:

    1. 变量的声明
    2. 变量的赋值 
    let node = {
        type: "Identifier",
        name: "foo"
    };
    let { type, name } = node;
    console.log(type); // "Identifier"
    console.log(name); // "foo"

    数组解构 

    基本:let [a, b, c] = [1, 2, 3];// a = 1 // b = 2 // c = 3

    可嵌套:let [a, [[b], c]] = [1, [[2], 3]];  // a = 1 // b = 2 // c = 3

    可忽略:let [a, , b] = [1, 2, 3]; // a = 1 // b = 3

    不完全解构:let [a = 1, b] = []; // a = 1, b = undefined

    剩余运算符:let [a, ...b] = [1, 2, 3]; //a = 1 //b = [2, 3]

    字符串等:let [a, b, c, d, e] = 'hello'; // a = 'h' // b = 'e' // c = 'l' // d = 'l' // e = 'o'

    对象模型解构

    基本:

    let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
    // foo = 'aaa'
    // bar = 'bbb'
     
    let { baz : foo } = { baz : 'ddd' };
    // foo = 'ddd'

     可嵌套可忽略

    let obj = {p: ['hello', {y: 'world'}] };
    let {p: [x, { y }] } = obj;
    // x = 'hello'
    // y = 'world'
    let obj = {p: ['hello', {y: 'world'}] };
    let {p: [x, {  }] } = obj;
    // x = 'hello'

    不完全解构

    let obj = {p: [{y: 'world'}] };
    let {p: [{ y }, x ] } = obj;
    // x = undefined
    // y = 'world'

     剩余运算符

    let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40};
    // a = 10
    // b = 20
    // rest = {c: 30, d: 40}

    解构默认值

    let {a = 10, b = 5} = {a: 3};
    // a = 3; b = 5;
    let {a: aa = 10, b: bb = 5} = {a: 3};
    // aa = 3; bb = 5;

    11.promise(异步)--解决异步问题

    promise是回调地狱的一个解决方案 

    promise是一个对象,可以获取异步操作的消息,promise提供统一的API,各种异步操作都能处理

    2个特点:

    • 对象的状态不受外界影响 (3种状态)
      • Pending状态(进行中)
      • Fulfilled状态(已成功)
      • Rejected状态(已失败)
    • 一旦状态改变就不会再变 (两种状态改变:成功或失败)
      • Pending -> Fulfilled
      • Pending -> Rejected
    var promise = new Promise(function(resolve, reject){
        // ... some code
        if (/* 异步操作成功 */) {
            resolve(value);
        } else {
            reject(error);
        }
    })

     Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject。它们是两个函数,由JavaScript引擎提供,不用自己部署。
     resolve作用是将Promise对象状态由“未完成”变为“成功”,也就是Pending -> Fulfilled,在异步操作成功时调用,并将异步操作的结果作为参数传递出去;而reject函数则是将Promise对象状态由“未完成”变为“失败”,也就是Pending -> Rejected,在异步操作失败时调用,并将异步操作的结果作为参数传递出去。

    then:

     Promise实例生成后,可用then方法分别指定两种状态回调参数。then 方法可以接受两个回调函数作为参数:

    1. Promise对象状态改为Resolved时调用 (必选)
    2. Promise对象状态改为Rejected时调用 (可选)
     routeInfo (type = 'edit') {
        return new Promise((resolve, reject) => {
          this.listData(type).then(result => {
            return new Promise((resolve) => {
              let res = result.list[0]
              if (result.list.length !== 1) {
                console.warn('待办结果不唯一')
              }
              resolve(res)
            })
          }).then(res => {
            this.dataValidator(res, type).then(res => {
              resolve({
                name: this.info[this.typeCode][type].routerName,
                query: this.info[this.typeCode][type].query(res),
                params: this.info[this.typeCode][type].params && this.info[this.typeCode][type].params(res)
              })
            }).catch(e => {
              reject(e)
            })
          }).catch(e => {
            reject(e)
          })
        })
      }

    all:多个请求一起发出并根据请求顺序获取和使用数据的场景

        getData () {
          Promise.all([
            this.getCreditData(),
            this.getProjectData()
          ]).then(result => {
          }).finally(() => {
            this.loading.detail = false
          })
        },

     catch:reject状态时才会进入,捕获错误信息

    let p2 = new Promise((resolve, reject) => {
            reject('123');
    }).catch(e => e);

    finally() :不管Promise对象成功失败都进finally,都会执行的操作

    Promise.then(result => {}).catch(error => {}).finally(() =>{})

    图灵社区

    11.Symbol(第七种基本数据类型)

    Symbol是一种基本类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的

    好处:用来定义对象的唯一属性名(类似于id一样是唯一标识)

    缺点:Symbol类型是不能通过Object.keys()或者for...in来枚举,因为不包含在对象自身的属性名集合(property name)中

    因此:使用JSON.stringify()将对象转成JSON字符串的时候,Symbol这个属性也会排除在外

    (1)为什么引入Symbol?

    之前的对象属性名是字符串,容易造成属性名冲突

    (2)typeof运算符用于Symbol类型值,返回symbol

    let name = Symbol()
    console.log(typeof name)   // Symbol

    (3)Symbol的值和谁都不相等,是独一无二的值.

     let symbol1 = Symbol()
     let symbol2 = Symbol()
     console.log(symbol1 === symbol2)  // false
     console.log(symbol1 == symbol2)   // false
     symbol1和symbol2相等吗?

    不相等.因为Symbol类型的值是独一无二的值.

    (4).为什么Symbol不能用new关键字?

    let obj = new Symbol()     // TypeError

    symbol值不是对象,所以不能添加属性

    (5)console.log(Symbol(‘Alice’) + “bruce”)   // TypeError,为什么错误?

    Symbol值不能与其他类型的值进行运算

    (6)如何读取Symbol的属性值?

     let name = Symbol()
     let obj = {}
     obj[name] = “Alice”
     cosnole.log(obj[name])

    Symbol值定义属性时,必须放在方括号内,不能用点运算符。

    (7)Symbol的值显示的转成字符串或者布尔值,但是不能转成数值.

    (8)获取对象属性的两种方法

      Object.getOwnPropertySymbols()   和  Object.getOwnPropertyNames() 

    12.解构赋值

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值

    类模板字符串的功能

    let name = 'web';
    let age = 10;
    let str = '你好,${name} 已经 ${age}岁了'
    str = str.replace(/\$\{([^}]*)\}/g,function(){
         return eval(arguments[1]);
    })
    console.log(str);//你好,web 已经 10岁了

    js面试笔试--ES6的解构_evior-CSDN博客

    ================开始不用看 

    了解axios和fetch 

    9.import、export导入导出

    ES6标准中,Js原生支持模块(module)。将JS代码分割成不同功能的小块进行模块化,将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用

    什么是Proxy? (代理--不会)

    Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”,即对编程语言进行编程。

    Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

    93.requireJS的核心原理是什么? 

    require.js 的核心原理是通过动态创建 script 脚本来异步引入模块,然后对每个脚本的 load 事件进行监听,如果每个脚本都加载完成了,再调用回调函数。 

    三种事件模型是什么? 

    事件 是用户操作网页时发生的交互动作或者网页本身的一些操作,现代浏览器一共有三种事件模型。

    1. DOM0级模型: ,这种模型不会传播,所以没有事件流的概念,但是现在有的浏览器支持以冒泡的方式实现,它可以在网页中直接定义监听函数,也可以通过 js属性来指定监听函数。这种方式是所有浏览器都兼容的。

    2. IE 事件模型: 在该事件模型中,一次事件共有两个过程,事件处理阶段,和事件冒泡阶段。事件处理阶段会首先执行目标元素绑定的监听事件。然后是事件冒泡阶段,冒泡指的是事件从目标元素冒泡到 document,依次检查经过的节点是否绑定了事件监听函数,如果有则执行。这种模型通过 attachEvent 来添加监听函数,可以添加多个监听函数,会按顺序依次执行。

    3. DOM2 级事件模型: 在该事件模型中,一次事件共有三个过程,第一个过程是事件捕获阶段。捕获指的是事件从 document 一直向下传播到目标元素,依次检查经过的节点是否绑定了事件监听函数,如果有则执行。后面两个阶段和 IE 事件模型的两个阶段相同。这种事件模型,事件绑定的函数是 addEventListener,其中第三个参数可以指定事件是否在捕获阶段执行。

     92.JS中的宿主对象与原生对象有何不同? 请指出 JavaScript 宿主对象 (host objects) 和原生对象 (native objects) 的区别?)

    宿主对象:这些是运行环境提供的对象。这意味着它们在不同的环境下是不同的。例如,浏览器包含像windows这样的对象,但是Node.js环境提供像Node List这样的对象。 Javascript内置对象、原生对象、宿主对象关系_每天=生命的最后一天-CSDN博客

    原生对象:这些是JS中的内置对象。它们也被称为全局对象,因为如果使用JS,内置对象不受是运行环境影响。

     js 获取原型的方法?

    •  p.proto
    • p.constructor.prototype
    • Object.getPrototypeOf(p)

    从构造函数获得原型对象:  构造函数.prototype

    从对象实例获得父级原型对象:1.对象实例._proto_       2.Object.getPrototypeOf(对象实例)

    function Student(){
        this.name = "小马扎"; 
        this.age = 18;
    }
    var lilei = new Student();  // 创建对象实例
    console.log(Student.prototype);  //Student{}
    console.log(lilei.__proto__);  //Student{}
    console.log(Object.getPrototypeOf(lilei));    //Student{}

     JS中为什么需要原型对象

    JS使用构造函数创建对象时,每个实例对象的方法都存放在独立的内存中,不能共享;使用原型对象可以解决上面浪费内存空间。

    https://jingyan.baidu.com/article/597a0643a743aa712b52439b.html

    JavaScript如果实现继承? 
    1、构造函数继承
    2、原型链继承
    3、实例继承
    4、拷贝继承
    原型prototype机制或apply和call方法去实现较简单、建议使用构造函数与原型混合方式
    function Parent(){
        this.name = "shen";
    }
    function Child(){
        this.age = 23;
    }
    Child.prototype = new Parent();
    var Demo = new Child();
    console.log(Demo.age);
    console.log(Demo.name);

    JavaScript原型、原型链?有什么特点? 

    什么是原型:原型是一个对象、其他对象可以通过它实现属性继承(任何对象都可以成为原型)
    所有对象在默认情况下都有一个原型(原型本身就是个对象)
    什么是对象(任何无序键值对的集合)如果它不是基本数据类型、那它就是一个对象
    原型链:当我们访问这个对象的属性时、如果这个对象内部不存在这个属性、那么他就回去prototype里去查找、这个prototype又有自己的prototype属性。这样一直找下去。就是平时说的原型链概念
    关系:instance.constructor.prototype = instance.__proto__
    当我们需要一个属性时、JavaScript引擎会先查看当前对象中是否有这个属性
    如果没有、就会查找他的prototype对象是否有这个属性、依次递推下去、一直检索到Object内检对象
    function Func(){}
    Func.prototype.name = "shen";
    Func.prototype.getInfo = function(){
        return this.name;
    }
    var person = new Func();
    console.log(person.getInfo());
    console.log(Func.prototype);
     
    var a = {};
    a.__proto__ = Array.prototype;
    a.length;
    创建a、然后通过a的原型来达到继承Array这个已经存在的对象的功能。
    原型真正的美丽提现在多个实例、共用一个通用原型
    原型对象的属性一旦定义、就可以被多个引用它的实例所继承、性能和未还的意义是很强的(这也是构造函数存在的意义)
    每个函数都有一个原型属性。JavaScript没有在构造函数(constructor)和其他函数之间做区分。

    请分别用深度优先思想和广度优先思想实现一个拷贝函数? 

    https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/10

    ES5/ES6 的继承除了写法以外还有什么区别? 

    先看ES5的继承(原型链继承)

    function a() {
      this.name = 'a';
    }
    a.prototype.getName = function getName() {
      return this.name
    }
    function b() {}
    b.prototype = new a();
    console.log(b.prototype.__proto__ === a.prototype); // true
    console.log(b.__proto__ === a); // false
    console.log(b.__proto__); // [Function]

     ES6继承

    class A {
      constructor(a) {
        this.name = a;
      }
      getName() {
        return this.name;
      }
    }
    
    class B extends A{
      constructor() {
        super();
      }
    }
    
    console.log(B.prototype.__proto__ === A.prototype); // true
    console.log(B.__proto__ === A); // true
    console.log(B.__proto__); // [Function: A]

    对比代码可以知道,子类的继承都是成功的,但是问题出在,子类的 __proto__ 指向不一样。

    ES5 的子类和父类一样,都是先创建好,再实现继承的,所以它们的指向都是 [Function] 。

    ES6 则得到不一样的结果,它指向父类,那么我们应该能推算出来,它的子类是通过 super 来改造的。

    根据 es6--阮一峰 在class继承里面的说法,是这样子的:

     引用阮一峰的 ECMAScript6入门 的class继承篇

    子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

    ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this

    1、class 声明会提升,但不会初始化赋值。Foo 进入暂时性死区,类似于 let、const 声明变量。

    2、class 声明内部会启用严格模式。

    3、class 的所有方法(包括静态方法和实例方法)都是不可枚举的。

    4、class 的所有方法(包括静态方法和实例方法)都没有原型对象 prototype,所以也没有[[construct]],不能使用 new 来调用。

    5、必须使用 new 调用 class。

    6、class 内部无法重写类名

    setTimeout、Promise、Async/Await 的区别

    其中settimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行; promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行;async函数表示函数里面可能会有异步方法,await后面跟一个表达式,async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行。

    谈谈以前端角度出发做好SEO需要考虑什么? 

    Meta标签优化
    主要包括主题(Title),网站描述(Description),和关键词(Keywords)。还有一些其它的隐藏文字比如Author(作者),Category(目录),Language(编码语种)等。
    合理的标签使用 

    JavaScript中、有一个函数、执行对象查找时、永远不会去查找原型、这个

    hasOwnProperty:当前函数返回的是一个布尔值、指出一个对象是否具有指定名称的属性、此方法无法检查该对象的原型链中是否具有该属性(该属性必须是对象本身的一个成员属性)
    object.hasOwnProperty(prName);
    参数object是必选项、一个对象是实例
    参数proName是必选项。一个属性名称的字符串值。
    如果object具有制定名称的属性、那么JavaScript中的hasOwnProperty函数方法返回true、反之则返回false

    JavaScript设计模式

    • 单例模式
    • 适配器模式
    • 代理模式
    • 发布-订阅模式
    • 策略模式
    • 迭代器模式

    52.ajax原理:

    1. 创建对象   var xhr = new XMLHTTPRequest()
    2. 打开请求  xhr.open('GET','example.txt',true)
    3. 发送请求  xhr.send()
    4. 接收响应数据  xhr.onready.stateChange = function()

    60.输出今天的日期,以YYYY-MM-DD的方式,比如今天是2014年9月26日,则输出2014-09-26

    考点:日期对象Date相关API的使用      var d = new Date();

    65.foo = foo||bar ,这行代码是什么意思?为什么要这样写?

    var foo;
    if(foo){
        foo=foo;
    }else{
        foo=bar;
    }

    答案:常用于函数参数的空判断
    短路表达式:作为”&&”和”||”操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值。
    考点:if条件的真假判定
    记住以下是false的情况:空字符串、false、undefined、null、0

    (头条、微医)Async/Await 如何通过同步的方式实现异步 

    async await 用于把异步请求变为同步请求的方式,第一个请求的返回值作为后面一个请求的参数,其中每一个参数都是一个promise对象

    例如:这种情况工作中会经常遇到

    (async () => {
        var a = await A();
        var b = await B(a);
        var c = await C(b);
        var d = await D(c);
    })();

    (头条)异步笔试题 

    请写出下面代码的运行结果

    async function async1() {
        console.log('async1 start');
        await async2();
        console.log('async1 end');
    }
    async function async2() {
        console.log('async2');
    }
    console.log('script start');
    setTimeout(function() {
        console.log('setTimeout');
    }, 0)
    async1();
    new Promise(function(resolve) {
        console.log('promise1');
        resolve();
    }).then(function() {
        console.log('promise2');
    });
    console.log('script end');

    (携程)算法手写题

    已知如下数组:

    var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];

    编写一个程序将数组扁平化去并除其中重复部分数据,最终得到一个升序且不重复的数组

     var arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];
        // 方法一
        console.log(Array.from(new Set(arr.flat(Infinity))).sort((a, b) => a - b))
        // 方法二
        console.log(Array.from(new Set(arr.toString().split(','))).map(Number).sort((a, b) => a - b))
    
        // 方法三
        // 第一步:扁平化
        let newArr = [];
        function flat(originArr) {
            if ({}.toString.call(originArr) === '[object Array]') {
                for (let i of originArr) {
                    if ({}.toString.call(i) === '[object Array]') {
                        arguments.callee(i)
                    } else {
                        newArr.push(i)
                    }
                }
            }
            return newArr;
        }
        console.log(flat(arr))
        // 第二步:去重
        var newArr1 = [];
        for (let i of newArr) {
            if (!newArr1.includes(i)) newArr1.push(i);
        }
        // 第三步:排序 可以采用相关算法处理
        console.log(newArr1.sort((a, b) => a - b))

    (兑吧)情人节福利题,如何实现一个 new 

    先理清楚 new 关键字调用函数都的具体过程,那么写出来就很清楚了

    首先创建一个空的对象,空对象的 ___proto____属性指向构造函数的原型对象
    把上面创建的空对象赋值构造函数内部的this,用构造函数内部的方法修改空对象
    如果构造函数返回一个非基本类型的值,则返回这个值,否则上面创建的对象 

    function _new(fn, ...arg) {
        var obj = Object.create(fn.prototype);
        const result = fn.apply(obj, ...arg);
        return Object.prototype.toString.call(result) == '[object Object]' ? result : obj;
    }

    (网易)简单讲解一下http2的多路复用

    第 15 题:简单讲解一下 http2 的多路复用 · Issue #14 · Advanced-Frontend/Daily-Interview-Question · GitHub

    谈谈你对TCP三次握手和四次挥手的理解 

    https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/15

    A、B 机器正常连接后,B 机器突然重启,问 A 此时处于 TCP 什么状态 

    https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/21

    介绍下 npm 模块安装机制,为什么输入 npm install 就可以自动安装对应的模块? 

    https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/22

    找出多维数组最大值

    给字符串新增方法实现功能 

    找出字符串出现最多次数的字符以及次数 

    sort背后原理是什么? 

    JavaScript 中 this 是如何工作的

    JavaScript 中 this 是如何工作的 ? - 前端の战士 - 博客园

    一般this指向调用者,箭头函数的this,指向调用的父作用域

    call ,apply,bind修改this

    页面重构怎么操作?

    • 结构完整,可通过标准验证
    •  标签语义化,结构合理
    • 充分考虑到页面在站点中的“作用和重要性”,并对其进行有针对性的优化

    js继承的6种方式

    JS实现继承的几种方式 - 幻天芒 - 博客园

    new实现 

    js new一个对象的过程,实现一个简单的new方法 - 听风是风 - 博客园

    列出JS中的一些设计模式:

    1. 创建模式:该模式抽象了对象实例化过程。
    2. 结构型模式:这些模式处理不同的类和对象以提供新功能。
    3. 行为模式:也称发布-订阅模式,定义了一个被观察者和多个观察者的、一对多的对象关系。
    4. 并行设计模式:这些模式处理多线程编程范例。
    5. 架构设计模式:这些模式用于处理架构设计。

    如何在现有函数中添加新属性

     只需给现有函数赋值,就可以很容易地在现有函数中添加新属性。例如,现有一个对象person,通过下面的代码来为 person 添加新的属性:

    person.country= “India”;

    JavaScript 原型,原型链?有什么特点? 

     每个对象都会在其内部初始化一个属性,就是prototype(原型)==(在JavaScript中,每个函数都有一个prototype属性,这个属性指向函数的原型对象。)

    function Person(age) {
        this.age = age       
    }
    Person.prototype.name = 'kavin'
    var person1 = new Person()
    var person2 = new Person()
    console.log(person1.name) //kavin
    console.log(person2.name)  //kavin

    javascript——原型与原型链 - 雅昕 - 博客园

    原型链:当我们去访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里面找这个属性,这个属性prototype就会有自己的prototype。
    就这样一层一层的寻找,也就是我们平时所说的原型链的概念。

    关系

    instance.constructor.prototype=instance._proto_

    JavaScript 对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与
    之相关的对象也会继承这一改变。 

    谈谈你对模块化开发的理解? 

    1.  我对模块的理解是,一个模块是实现一个特定功能的一组方法。在最开始的时候,js 只实现一些简单的功能,所以并没有模块的概念,但随着程序越来越复杂,代码的模块化开发变得越来越重要。
    2. 由于函数具有独立作用域的特点,最原始的写法是使用函数来作为模块,几个函数作为一个模块,但是这种方式容易造成全局变量的污染,并且模块间没有联系。
    3. 后面提出了对象写法,通过将函数作为一个对象的方法来实现,这样解决了直接使用函数作为模块的一些缺点,但是这种办法会暴露所有的所有的模块成员,外部代码可以修改内部属性的值。
    4. 现在最常用的是立即执行函数的写法,通过利用闭包来实现模块私有作用域的建立,同时不会对全局作用域造成污染。

     js 的几种模块规范? 

    js 中现在比较成熟的有四种模块加载方案:

    • 第一种是 CommonJS 方案,它通过 require 来引入模块,通过 module.exports 定义模块的输出接口。这种模块加载方案是服务器端的解决方案,它是以同步的方式来引入模块的,因为在服务端文件都存储在本地磁盘,所以读取非常快,所以以同步的方式加载没有问题。但如果是在浏览器端,由于模块的加载是使用网络请求,因此使用异步加载的方式更加合适。

    • 第二种是 AMD 方案,这种方案采用异步加载的方式来加载模块,模块的加载不影响后面语句的执行,所有依赖这个模块的语句都定义在一个回调函数里,等到加载完成后再执行回调函数。require.js 实现了 AMD 规范。

    • 第三种是 CMD 方案,这种方案和 AMD 方案都是为了解决异步模块加载的问题,sea.js 实现了 CMD 规范。它和require.js的区别在于模块定义时对依赖的处理不同和对依赖模块的执行时机的处理不同。

    • 第四种方案是 ES6 提出的方案,使用 import 和 export 的形式来导入导出模块。这种方案和上面三种方案都不同。

    61.JavaScript事件循环机制相关问题 

    关键字:单线程非阻塞、执行栈、事件队列、宏任务(setTimeout()、setInterval(),setTimeout、setInterval、script、setImmedate、IO、Promise.resolve)、微任务(new Promise(),process.nextTick、Promise、async await、mutation observer)

    • 宏任务、微任务、同步任务的执行顺序
      setTimeout(function () {
          console.log(1);
      });
       
      new Promise(function(resolve,reject){
          console.log(2)
          resolve(3)
      }).then(function(val){
          console.log(val);
      })
      console.log(4);
      // 2
      // 4
      // 3
      // 1

      先按顺序执行同步任务,Promise新建后立即执行输出2,接着输出4,异步任务等同步任务执行完后执行,且同一次事件循环中,微任务永远在宏任务之前执行。这时候执行栈空了,执行事件队列,先取出微任务,输出3,最后取出一个宏任务,输出1。

    事件循环--浏览器

    执行宏任务,然后执行该宏任务产生的微任务,若微任务在执行过程中产生了新的微任务,则继续执行微任务,微任务执行完毕后,再回到宏任务中进行下一轮循环。

    对象是什么? 

    arguments对象是函数中传递的参数值的集合。它是一个类似数组的对象,因为它有一个length属性,我们可以使用数组索引表示法arguments[1]来访问单个值,但它没有数组中的内置方法,如:forEach、reduce、filter和map。

    我们可以使用Array.prototype.slice将arguments对象转换成一个数组。

    function one() {
      return Array.prototype.slice.call(arguments);
    }

     注意:箭头函数中没有arguments对象。

    function one() {
      return arguments;
    }
    const two = function () {
      return arguments;
    }
    const three = function three() {
      return arguments;
    }
    
    const four = () => arguments;
    
    four(); // Throws an error  - arguments is not defined

    当我们调用函数four时,它会抛出一个ReferenceError: arguments is not defined error。使用rest语法,可以解决这个问题

    const four = (...args) => args;

     这会自动将所有参数值放入数组中。

     ES6 模块与 CommonJS 模块、AMD、CMD 的差异。 

    https://blog.csdn.net/u013681954/article/details/97299399

     generator

    调用之后会返回一个value、next 和done,value表示当前的值,done表示是否结束,结束后值为 true,每次执行都需要调用next才会继续执行 

    9.修饰器 @

    decorator是一个函数,用来修改类甚至于是方法的行为。修饰器本质就是编译时执行的函数

    10.class 类的继承

    ES6中不再像ES5一样使用原型链实现继承,而是引入Class这个概念

    23.Promise 中reject 和 catch 处理上有什么        区别

    reject 是用来抛出异常,catch 是用来处理异常

    reject 是 Promise 的方法,而 catch 是 Promise 实例的方法

    reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch

    网络异常(比如断网),会直接进入catch而不会进入then的第二个回调

    14.Proxy代理

    使用代理(Proxy)监听对象的操作,然后可以做一些相应事情

    15.ECMAScript 6 怎么写 class ,为何会出现 class?

    ES6的class可以看作是一个语法糖,它的绝大部分功能ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法

    //定义类
    class Point { 
      constructor(x,y) { 
          //构造方法
           this.x = x; //this关键字代表实例对象
           this.y = y; 
      } toString() {
           return '(' + this.x + ',' + this.y + ')'; 
      }
    }

    19.下面的输出结果是多少

    const promise = new Promise((resolve, reject) => {
        console.log(1);
        resolve();
        console.log(2);
    })
    
    promise.then(() => {
        console.log(3);
    })
    
    console.log(4); //1 2 4 3

    Promise 新建后立即执行,所以会先输出 1,2,而 Promise.then() 内部的代码在 当次 事件循环的 结尾 立刻执行 ,所以会继续输出4,最后输出3

    20.使用结构赋值,实现两个变量的值的交换

    let a = 1;let b = 2;
    [a,b] = [b,a];

    21.设计一个对象,键名的类型至少包含一个symbol类型,并且实现遍历所有key

     let name = Symbol('name');
     let product = {
        [name]:"洗衣机",    
        "price":799
      };
      Reflect.ownKeys(product);

    22.下面Set结构,打印出的size值是多少

    let s = new Set();
    s.add([1]);
    s.add([1]);console.log(s.size);  //2

    两个数组[1]并不是同一个值,它们分别定义的数组,在内存中分别对应着不同的存储地址,因此并不是相同的值。都能存储到Set结构中,所以size为2

    24.使用class 手写一个promise

    //创建一个Promise的类
      class Promise{
        constructor(executer){//构造函数constructor里面是个执行器
          this.status = 'pending';//默认的状态 pending
          this.value = undefined//成功的值默认undefined
          this.reason = undefined//失败的值默认undefined
          //状态只有在pending时候才能改变
          let resolveFn = value =>{
            //判断只有等待时才能resolve成功
            if(this.status == pending){
              this.status = 'resolve';
              this.value = value;
            }
          }
          //判断只有等待时才能reject失败
          let rejectFn = reason =>{
            if(this.status == pending){
              this.status = 'reject';
              this.reason = reason;
            }
          }    
          try{
            //把resolve和reject两个函数传给执行器executer
            executer(resolve,reject);
          }catch(e){
            reject(e);//失败的话进catch
          }
        }
        then(onFufilled,onReject){
          //如果状态成功调用onFufilled
          if(this.status = 'resolve'){
            onFufilled(this.value);
          }
          //如果状态失败调用onReject
          if(this.status = 'reject'){
            onReject(this.reason);
          }
        }
      }

    29.说一下es6的导入导出模块

    // 只导入一个
    import {sum} from "./example.js"
    // 导入多个
    import {sum,multiply,time} from "./exportExample.js"
    // 导入一整个模块
    import * as example from "./exportExample.js"

    导出通过export关键字

    //可以将export放在任何变量,函数或类声明的前面
    export var firstName = 'Michael';
    export var lastName = 'Jackson';
    export var year = 1958;
    
    //也可以使用大括号指定所要输出的一组变量
    var firstName = 'Michael';
    var lastName = 'Jackson';
    var year = 1958;
    export {firstName, lastName, year};
    
    //使用export default时,对应的import语句不需要使用大括号
    let bosh = function crs(){}
    export default bosh;
    import crc from 'crc';
    
    //不使用export default时,对应的import语句需要使用大括号
    let bosh = function crs(){}
    export bosh;
    import {crc} from 'crc';

    13.堆栈内存(没看)

    当浏览器加载页面时,会形成两个虚拟的内存;一个栈内存,堆内存;

    栈内存:

    1. 提供代码的运行环境;
    2. 存储基本数据类型;

    堆内存: 存储引用数据类型

    28.函数的递归

    递归: 针对的是函数; 是JS中一种重要的思想; 
    函数: 分为定义和执行 
    函数递归: 在函数体内部,调用函数自己本身,让其执行;这就是递归;

    function sum(num) {
    if(num === 0){
    return num;
    }
    if(num%3===0){
    return num + sum(num-1);
    }
    if(num%3!==0){
    return sum(num-1);
    }
    // return sum(99)
    // return 99 + sum(98)
    // return 99 + sum(97)
    // return 99 + sum(96)
    // return 99 + 96 + sum(95)....
    // return 99 + 96 +... + 3 + sum(2)
    // return 99 + 96 +... + 3 + sum(1)
    // return 99 + 96 +... + 3 + 0
    }
    console.log(sum(100));
    console.log(sum(200));

    29.求1-100之间是3倍数的和(% : 取模;取余数)

    var total = 0;
    for(var i=0;i<100;i++){
    if(i%3===0){
    total += i;
    }
    }

    30.数组的插入排序

    var ary = [12,88,67,98,56,35,45,26,1];
    //5 6 7 8 10
    //得到的新数组是排好序
    //插入排序原理:去原有数组中去取每一项,然后和新数组中的成员进行比较,从新数组后面开始,一一向前比较,比新数组项小,继续和前一项比较,直到当前项比数组中一项值大时,把它放到这一项的后面;
    var newAry = [];
    newAry.push(ary[0]);
    for(var i=1;i<ary.length;i++){
    var cur = ary[i];
    for(var j=newAry.length-1;j>=0;j--){
    if(cur<newAry[j]){// 如果数组中拿到的这一项比新数组中j的这一项小;那么继续j--;和上一个成员进行比较;
    if(j===0){
    newAry.unshift(cur);
    break;// 只会中止当前的小循环
    }
    }else{
    // cur<newAry[j]的情况,把当前项放到新数组这一项的后面;
    newAry.splice(j+1,0,cur);
    break;
    }
    }
    }
    // 从前向后
    console.log(newAry);
    var ary = [12,88,67,98,56,35,45,26,1];
    var mAry = [12,67,88];
    mAry.push(ary[0]);
    for(var i=1;i<ary.length;i++){
    var cur = ary[i];
    for(var j = mAry.length-1;j>=0;j--){
    if(cur<mAry[j]){
    if(j===0){
    mAry.unshift(cur);
    break;
    }
    }else{
    mAry.splice(j+1,0,cur);
    break;
    }
    }
    }

    32.随机验证码

    var code = document.getElementById("code");
    function getCode() {
    // 准备一个62个字符串;
    // 产生随机数;随机数可以作为字符的索引;
    // 随机索引范围【0-61】
    var str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    // 随机数;
    var i =0;
    var newStr = "";
    while(i<4){
    var num = Math.round(Math.random()*(61-0)+0);
    newStr+=str[num];
    i++;
    }
    code.innerHTML = newStr;
    }
    getCode();
    // 把函数的空间地址赋值给code的onclick属性;
    code.onclick = getCode;

    43.看下列代码会有什么样的输出?

    var foo = "11"+2-"1";  
    console.log(foo);//112-1=111
    console.log(typeof foo);//”number”

    考点:
    1、数字和字符串都可以用加法运算符,数字和字符串相加,结果就是一个字符串
    2、但是减法运算符只能用于两个数字之间,想要执行减法运算,必须把两边数字都变成数字类型的
    答案:”111”、”number”

    45.已知数组var stringArray = [“This”, “is”, “Baidu”, “Campus”],alert出”This is Baidu Campus”。

    考点:数组的join方法的使用,将一个数组通过指定字符分隔组成一个想要的字符串
    答案:alert(stringArray.join(“ ”))

    46.已知有字符串foo=”get-element-by-id”,写一个function将其转化成驼峰表示法”getElementById”。

        function combo(msg){
        var arr=msg.split("-");//[get,element,by,id]
        for(var i=1;i<arr.length;i++){
            arr[i]=arr[i].[0].toUpperCase()+arr[i].substring(1);//Element
        }
        msg=arr.join("");//msg=” getElementById”
        return msg;
    }

    47.var numberArray = [3,6,2,4,1,5];

    1)实现对该数组的倒排,输出[5,1,4,2,6,3]

    function reverseArray(arr){
        var result=[];
        //方法1:
        /*for (var i = arr.length - 1; i >= 0; i--) {
            result.push(arr[i]);
        }*/
        //方法2:
        for (var i = 0, len = arr.length; i < len; i++) {
            result.unshift(arr[i]);
        }
        return result;
    }

    2)实现对该数组的降序排列,输出[6,5,4,3,2,1]

    function sortDesc(arr) {
        for (var i = 0, len = arr.length; i < len; i++) {
            for (var j = i + 1, len2 = arr.length; j < len2; j++) {
                //>就是降序 <就是升序
                if (arr[j] > arr[i]) {
                    var temp = arr[j];
                    arr[j] = arr[i];
                    arr[i] = temp;
                }
            }
        }
        return arr;
    }

    51.用js实现随机选取10–100之间的10个数字,存入一个数组,并排序。

    var iArray = []; 
    function getRandom(istart, iend){
            var iChoice = iend - istart +1;
            return Math.floor(Math.random() * iChoice+ istart);
    }
    Math.random()就是获取0-1之间的随机数(永远获取不到1)
    for(var i=0; i<10; i++){
    var result= getRandom(10,100);
            iArray.push(result);
    }
    iArray.sort();

    52.把两个数组合并,并删除第二个元素。

    考点:1、数组的concat、splice用法
    splice() 方法删除数组的元素,或者向数组中添加元素,然后返回被删除的项目。
    参数1:从何处开始删除数组的元素(使用负数则从数组的末尾开始)
    参数2:要删除的元素个数(如果是0,就代表不删除)
    参数3,4,5。。。:要添加的元素

    var array1 = ['a','b','c'];
    

    var bArray = [‘d’,’e’,’f’];
    var cArray = array1.concat(bArray);
    cArray.splice(1,1);

    54.Javascript中, 以下哪条语句一定会产生运行错误? 答案( BC )             ??????????????

    A、var _变量=NaN;      // 
    B、var 0bj = [];             // Invalid or unexpected token
    C、var obj = //;           
    D、var obj = {};
    //正确答案:BC

    56.Javascript创建对象的几种方式?

    构造函数方式,原型模式,混合构造函数原型模式,工厂方式,动态原型方式

    混合构造函数+原型模式:

    function Robot(name){
        this.name=name;
    }
    Robot.prototype.say=function(){
        alert("大家好,我叫"+this.name);
    };
    var alphaGo=new Robot("阿尔法狗");
    alphaGo.say();

    工厂方式:

    function create(name,age){
        var o={};
        o.name=name;
        o.age=age;
        return o;
    }
    var p1=create("张三",20);

    动态原型方式:

    function Person(name,work){
        this.name=name;
        if(work){
            Person.prototype.doWork=function(){
                alert("我正在从事"+work+"的工作");
            }
        }
    }
    var p1=new Person("姚明");
    var p2=new Person("喵喵","程序猿鼓励师");

    59.documen.write和 innerHTML 的区别?

    • document.write 指定位置输出
    • dom.innerHTML 可以重绘指定元素的内容
    • document.write和innerHTML的区别

    61.解释jsonp的原理,以及为什么不是真正的ajax

    动态创建script标签,回调函数
    Ajax是页面无刷新请求数据操作

    62.将数字 12345678 转化成 RMB形式 如: 12,345,678

    //思路:先将数字转为字符, str= str + ” ;
    //利用反转函数,每三位字符加一个 ‘,’最后一位不加; re()是自定义的反转函数,最后再反转回去!

    for(var i = 1; i <= re(str).length; i++){
        tmp += re(str)[i - 1];
        if(i % 3 == 0 && i != re(str).length){
            tmp += ',';
        }
    }

    64.什么是三元表达式 (Ternary expression)?“三元 (Ternary)” 表示什么意思?

    一个运算符如果有一个操作数,为一元运算符,两个为二元,三个为三元运算符,三元表达式则为一个三元运算表达式!

    71.如果某一个接口很缓慢,用户离开这个页面该怎么处理?

    93.js有几种弹出窗

    alert.confirm,prompt

    • alert:警告窗
    • confirm:确认窗口
    • prompt:信息输入窗口

     find和filter的区别

    展开全文
    qq_40055200 2021-11-11 12:22:03
  • weixin_43848576 2021-04-13 18:19:27
  • weixin_45622540 2021-01-19 15:19:13
  • qq_41555854 2021-01-11 12:01:28
  • yzm521314 2021-08-11 11:13:48
  • weixin_47731102 2021-01-08 11:57:03
  • wen110898 2021-10-13 01:51:59
  • qq_45272615 2021-10-24 15:56:36
  • LuckyWinty 2021-02-24 08:45:00
  • qq_39903567 2021-03-18 20:52:12
  • bznhlhh 2021-04-20 14:49:54
  • wzstd 2021-09-23 16:31:51
  • m0_58225312 2021-10-18 15:15:12
  • weixin_45706862 2021-09-19 21:17:06
  • weixin_43514933 2021-03-29 16:45:38
  • m0_59992220 2021-08-18 20:53:20
  • yangchengguo 2021-08-18 15:23:44
  • weixin_46034314 2021-01-06 20:38:50
  • qq_39056703 2021-09-30 12:00:31
  • qq95503282 2021-12-16 20:08:17
  • chenweiqiang77 2021-03-21 11:17:07
  • xgangzai 2021-07-05 10:43:10
  • qq_45272615 2021-10-16 22:53:44
  • qq_36380426 2021-02-14 11:00:49
  • qq_34998786 2021-01-07 13:54:13
  • QXXXD 2021-06-21 16:42:31

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,167
精华内容 9,666
关键字:

es6面试