近期收拾了一下高频的前端面试题,分享给我们一同来学习。如有问题,欢迎纠正!

欢迎我们重视该专栏:点赞 + 收藏

前端面试题系列文章:

【1】2022高频前端面试题——HTML篇

【2】2022高频前端面试题——CSS篇

【3】 2022高频前端面试题合集之JavaScript篇(上)

【4】 2022高频前端面试题合集之JavaScript篇(中)

JavaScript面试题汇总(下篇)

201. 冒泡排序的思路,不用 sort

参考答案:

示例代码如下:

var examplearr = [8, 94, 15, 88, 55, 76, 21, 39];
function sortarr(arr) {
    for (i = 0; i < arr.length - 1; i++) {
        for (j = 0; j < arr.length - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                var temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    return arr;
}
sortarr(examplearr);
console.log(examplearr); // [8, 15, 21, 39, 55, 76, 88, 94]

202. symbol 用途

参考答案:

能够用来表明一个绝无仅有的变量防止命名抵触。可是面试官问还有吗?我没想出其他的用途就直接答我不知道了,还能够运用 symbol 不会被常规的办法(除了 Object.getOwnPropertySymbols 外)遍历到,所以能够用来模拟私有变量。

首要用来供给遍历接口,布置了 symbol.iterator 的方针才干够运用 forof 循环,能够一致处理数据结构。调用之后回回来一个遍历器方针,包括有一个 next 办法,运用 next 办法后有两个回来值 value 和 done 别离表明函数当前履行方位的值和是否遍历完毕。

Symbol.for() 能够在大局拜访 symbol

203. 什么是函数式编程,运用场景是什么

参考答案:

函数式编程和面向方针编程相同,是一种编程范式。着重履行的进程而非成果,经过一系列的嵌套的函数调用,完结一个运算进程。 它首要有以下几个特色:

  1. 函数是”一等公民”:函数优先,和其他数据类型相同。
  2. 只用”表达式”,不用”句子”:经过表达式(expression)核算进程得到一个回来值,而不是经过一个句子(statement)修正某一个状态。
  3. 无副效果:不污染变量,同一个输入永久得到同一个数据。
  4. 不行变性:前面一说到,不修正变量,回来一个新的值。

函数式编程的概念其实出来也现已好几十年了,咱们能在许多编程言语身上看到它的身影。比方比较朴实的 Haskell,以及一些言语开端逐渐成为多范式编程言语,比方 Swift,还有 Kotlin,Java,Js 等都开端具备函数式编程的特性。

函数式编程在前端的运用场景

  • Stateless componentsReact0.14 之后推出的无状态组件
  • Redux

函数式编程在后端的运用场景

  • Lambda 架构

204. 事情以及事情相关的兼容性问题

参考答案:

事情最早是在 IE3Navigator2 中呈现的,当时是作为分管服务器运算负担的一种手法。要完结和网页的互动,就需求经过 JavaScript 里边的事情来完结。

每次用户与一个网页进行交互,例如点击链接,按下一个按键或许移动鼠标时,就会触发一个事情。咱们的程序能够检测这些事情,然后对此作出呼应。然后形成一种交互。

当咱们绑定事情时,需求遵从事情三要素

  • 事情源:是指那个元素引发的事情。比方当你点击图标的时分,会跳转到百度主页。那么这个图标便是事情源。
  • 事情:事情是指履行的动作。例如,点击,鼠标划过,按下键盘,取得焦点。
  • 事情驱动程序:事情驱动程序即履行的成果。例如,当你点击图标的时分,会跳转到百度主页。那么跳转到百度主页便是事情的处理成果。
事情源.事情 = function() {
    事情处理函数
}

205. JS 小数不精准,怎么核算

参考答案:

办法一:指定要保留的小数位数(0.1+0.2).toFixed(1) = 0.3;这个办法toFixed是进行四舍五入的也不是很精准,关于核算金额这种严谨的问题,不推荐运用,而且不同浏览器对toFixed的核算成果也存在差异。

办法二:把需求核算的数字晋级(乘以10的n次幂)成核算机能够精确辨认的整数,等核算完毕再降级(除以10的n次幂),这是大部分编程言语处理精度差异的通用办法。

206. 写一个 mySetInterVal(fn, a, b),每次距离 a,a+b,a+2b 的时间,然后写一个 myClear,停止上面的 mySetInterVal

参考答案:

该题的思路便是每一次在定时器中重启定时器而且在时间每一次都加 b,而且要把定时器回来回来,能够作为myClear的参数。

代码如下:

var mySetInterVal = function (fn, a, b) {
  var timer = null;
  var settimer = function (fn, a, b) {
    timer = setTimeout(() => {
      fn();
      settimer(fn, a + b, b);
    }, a);
  }
  settimer(fn, a, b);
  return timer;
}
var timer = mySetInterVal(() => { console.log('timer') }, 1000, 1000);
var myClear = function (timer) {
  timer && clearTimeout(timer);
}

207. 兼并二维有序数组成一维有序数组,归并排序的思路

参考答案:

示例代码如下:

function merge(left, right) {
    let result = []
    while (left.length > 0 && right.length > 0) {
        if (left[0] < right[0]) {
            result.push(left.shift())
        } else {
            result.push(right.shift())
        }
    }
    return result.concat(left).concat(right)
}
function mergeSort(arr) {
    if (arr.length === 1) {
        return arr
    }
    while (arr.length > 1) {
        let arrayItem1 = arr.shift();
        let arrayItem2 = arr.shift();
        let mergeArr = merge(arrayItem1, arrayItem2);
        arr.push(mergeArr);
    }
    return arr[0]
}
let arr1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 2, 3], [4, 5, 6]];
let arr2 = [[1, 4, 6], [7, 8, 10], [2, 6, 9], [3, 7, 13], [1, 5, 12]];
console.log(mergeSort(arr1))
console.log(mergeSort(arr2))

208. 给定一个字符串,请你找出其间不含有重复字符的最长子串的长度。

参考答案:

首要,咱们肯定需求封装一个函数,而这个函数接纳一个字符串作为参数,回来不含有重复字符的子串长度。来看下面的示例:

示例 1:

输入: “abcabcbb” 输出: 3 解说: 由于无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

输入: “bbbbb” 输出: 1 解说: 由于无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

输入: “pwwkew” 输出: 3 解说: 由于无重复字符的最长子串是 “wke”,所以其长度为 3。 请注意,你的答案有必要是 子串 的长度,“pwke” 是一个子序列,不是子串。

示例代码:

var lengthOfLongestSubstring = function (s) {
    var y = [];
    var temp = [];
    var maxs = 0;
    if (s == "") {
        return 0;
    }
    if (s.length == 1) {
        return 1;
    }
    for (var i = 0; i < s.length; i++) {
        if (temp.includes(s[i])) {
            y.push(temp.length);
            temp.shift();
            continue;
        } else {
            temp.push(s[i])
            y.push(temp.length);
        }
    }
    for (var j = 0; j < y.length; j++) {
        if (maxs <= y[j]) {
            maxs = y[j]
        }
    }
    return maxs;
};
// 测验
console.log(lengthOfLongestSubstring('abcabcbb')); // 3
console.log(lengthOfLongestSubstring('bbbbb')); // 1
console.log(lengthOfLongestSubstring('pwwkew')); // 3

209. 有一堆整数,请把他们分红三份,保证每一份和尽量持平(11,42,23,4,5,6 4 5 6 11 23 42 56 78 90)(滴滴 2020)

参考答案:

本道标题是一道调查算法的标题,首要是调查编程根本功和一定的想像力。

详细的完结如下:

function fun(total, n) {
    //先对整个数组进行排序
    total.sort((a, b) => a - b);
    //求和
    var sum = 0;
    for (var i = 0; i < total.length; i++) {
        sum += total[i];
    }
    var avg = Math.ceil(sum / n);
    //成果数组
    var result = []; //长度为n
    for (var i = 0; i < n; i++) {
        result[i] = [total.pop()];
        result[i].sum = result[i][0];
        //组成一个分数组
        while (result[i].sum < avg && total.length > 0) {
            for (var j = 0; j < total.length; j++) {
                if (result[i].sum + total[j] >= avg) {
                    result[i].push(total[j]);
                    result[i].sum += total[j];
                    break;
                }
            }
            if (j == total.length) {
                result[i].push(total.pop());
                result[i].sum += result[i][result[i].length - 1];
            } else {
                //从数组中移除此元素
                total.splice(j, 1);
            }
        }
        sum -= result[i].sum;
        avg = Math.ceil(sum / (n - 1 - i));
    }
    return result;
}
// 测验
var arr = [11, 42, 23, 4, 5, 6, 4, 5, 6, 11, 23, 42, 56, 78, 90];
console.log(fun(arr, 3));
// [
//     [ 90, 56, sum: 146 ],
//     [ 78, 42, 11, sum: 131 ],
//     [ 42, 23, 23, 11, 6, 6, 5, 5, 4, 4, sum: 129 ]
// ]

210. 手写发布订阅(头条2020)

参考答案:

示例代码如下:

<body>
    <div id="app">
        <p>this is a test</p>
        {{msg}}<input type="text" v-model="msg">{{msg}}
    </div>
    <script src="./index.js"></script>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg : ''
            }
        });
    </script>
</body>
/*
    1. 创立 Vue 结构函数
        在 Vue 结构函数中,调用了 observer 函数,该函数的效果便是对数据进行绑架
        绑架详细要做的事儿:仿制一份数据,可是不是单纯的仿制,而是增加了 getter、setter
    2. 书写 compile 函数。该函数首要效果于模板,从模板里边要提取信息
        提取的东西首要有两个:{{}}  和 v-model
    3. 创立发布者 Dep 的结构函数,假如数据产生改变,发布者就会遍历内部的数组(花名册),告知订阅者修正数据
    4. 创立订阅者 Watcher 的结构函数,假如有数据的改变,发布者就会告知订阅者,订阅者上面存在 update 办法,会进行修正
 */
function Vue(options){
    // this 代表 Vue 的实例方针,本例中便是 vm
    // options.data 这便是实践的数据 {msg : 'xiejie'}
    observer(this,options.data);
    this.$el = options.el;
    compile(this);
}
// 用于对模板进行信息提取,首要提取 {{}}  和 v-model,然后进行一些操作
// {{ }} 会成为调查者,v-model 所对应的控件来绑定事情
function compile(vm){
    var el = document.querySelector(vm.$el); // el 所对应的值为 <div id="app">...</div>
    var documentFragment = document.createDocumentFragment(); // 创立了一个空的文档碎片
    var reg = /{{(.*)}}/; // 创立正则表达式 匹配 {{ }}
    while(el.childNodes[0]){
        var child = el.childNodes[0]; // 将榜首个子节点存储到 child
        if(child.nodeType == 1){
            // 假如能够进入此 if,阐明该节点是一个元素节点
            for(var key in child.attributes){
                // 遍历该元素节点的每一个特色,拿到的便是 type="text" v-model="msg"
                var attrName = child.attributes[key].nodeName; // 获取特色名  type、v-model
                if(attrName === 'v-model'){
                    var vmKey = child.attributes[key].nodeValue; // 先获取特色值,也便是 msg
                    // 为该节点,也便是 <input type="text" v-model="msg"> 绑定一个 input 事情
                    child.addEventListener('input', function (event) {
                        vm[vmKey] = event.target.value; // 获取用户输入的值,然后改动 vm 里边的 msg 特色对应的值,注意这儿会触发 setter
                    })
                }
            }
        }
        if(child.nodeType == 3){
            // 假如能进入此 if,阐明该节点是一个文本节点
            if(reg.test(child.nodeValue)){
                // 假如能够进入到此 if,阐明是 {{ }},然后咱们要让其成为订阅者
                var vmKey = RegExp.$1; // 获取正则里边的捕获值,也便是 msg
                // 实例化一个 Watcher(订阅者),接纳 3 个参数:Vue 实例,该文本节点,捕获值 msg
                new Watcher(vm, child, vmKey);
            }
        }
        documentFragment.appendChild(el.childNodes[0]); // 将榜首个子节点增加到文档碎片里边
    }
    // 将文档碎片中节点从头增加到 el,也便是 <div id="app"></div> 下面
    el.appendChild(documentFragment);
}
// 新建发布者结构函数
function Dep() {
    // 将调查者增加到发布者内部的数组里边
    // 这样以便于告知一切的调查者去更新数据
    this.subs = [];
}
Dep.prototype = {
    // 将 watcher 增加到发布者内置的数组里边
    addSub: function (sub) {
        this.subs.push(sub);
    },
    // 遍历数组里边一切的 watcher,告知它们去更新数据
    notify: function () {
        this.subs.forEach(function (sub) {
            sub.update();
        })
    }
}
// 新建调查者 Watcher 结构函数
// 接纳 3 个参数:Vue 实例,文本节点 {{ msg }} 以及捕获内容 msg
function Watcher(vm, child, vmKey) {
    this.vm = vm; // vm 
    this.child = child; // {{ msg }}
    this.vmKey = vmKey; // msg
    Dep.target = this; // 将该调查者实例方针增加给 Dep.target
    this.update(); // 履行节点更新办法
    Dep.target = null; // 终究清空 Dep.target
}
Watcher.prototype = {
    // 节点更新办法
    update: function () {
        // 相当于:{{ msg }}.nodeValue = this.vm['msg']
        // 这样就更新了文本节点的值,由于这儿在获取 vm.msg,所以会触发 getter
        this.child.nodeValue = this.vm[this.vmKey];
    }
}
// 该函数的效果是用于数据侦听
function observer(vm,obj){
    var dep = new Dep(); // 新增一个发布者:发布者的效果是告知订阅者数据现已更改
    // 遍历数据
    for(var key in obj){
        // 将数据的每一项增加到 vm 里边,至此,vm 也有了每一项数据
        // 可是不是单纯的增加,而是设置了 getter 和 setter
        // 在获取数据时触发 getter,在设置数据时触发 setter
        Object.defineProperty(vm, key, {
            get() {
                console.log("触发get了");
                // 触发 getter 时,将该 watcher 增加到发布者保护的数组里边
                if (Dep.target) {
                    dep.addSub(Dep.target); // 往发布者的数组里边增加订阅者
                }
                console.log(dep.subs);
                return obj[key];
            },
            set(newVal) {
                console.log("触发set了");
                obj[key] = newVal;
                dep.notify(); // 发布者发出音讯,告知订阅者修正数据
            }
        });
    }
}

211. 手写用 ES6proxy 怎么完结 arr[-1] 的拜访(滴滴2020)

参考答案:

示例代码如下:

const proxyArray = arr => {
    const length = arr.length;
    return new Proxy(arr, {
        get(target, key) {
            key = +key;
            while (key < 0) {
                key += length;
            }
            return target[key];
        }
    })
};
var a = proxyArray([1, 2, 3, 4, 5, 6, 7, 8, 9]);
console.log(a[1]);  // 2
console.log(a[-10]);  // 9
console.log(a[-20]);  // 8

212. 下列代码履行成果

console.log(1);
setTimeout(() => {
    console.log(2);
    process.nextTick(() => {
        console.log(3);
    });
    new Promise((resolve) => {
        console.log(4);
        resolve();
    }).then(() => {
        console.log(5);
    });
});
new Promise((resolve) => {
    console.log(7);
    resolve();
}).then(() => {
    console.log(8);
});
process.nextTick(() => {
    console.log(6);
});
setTimeout(() => {
    console.log(9);
    process.nextTick(() => {
        console.log(10);
    });
    new Promise((resolve) => {
        console.log(11);
        resolve();
    }).then(() => {
        console.log(12);
    });
});

参考答案:

1 7 6 8 2 4 3 5 9 11 10 12

213. Number() 的存储空间是多大?假如后台发送了一个超越最大自己的数字怎么办

参考答案:

Math.pow(2, 53) ,53 为有效数字,会产生截断,等于 JS 能支撑的最大数字。

214. 事情是怎么完结的?(字节2020)

参考答案:

根据发布订阅办法,便是在浏览器加载的时分会读取事情相关的代码,可是只需实践等到详细的事情触发的时分才会履行。

比方点击按钮,这是个事情(Event),而负责处理事情的代码段一般被称为事情处理程序(Event Handler),也便是「启动对话框的显现」这个动作。

在 Web 端,咱们常见的便是 DOM 事情:

  • DOM0 级事情,直接在 html 元素上绑定 on-event,比方 onclick,撤销的话,dom.onclick = null,同一个事情只能有一个处理程序,后边的会掩盖前面的。
  • DOM2 级事情,经过 addEventListener 注册事情,经过 removeEventListener 来删去事情,一个事情能够有多个事情处理程序,按次序履行,捕获事情和冒泡事情
  • DOM3级事情,增加了事情类型,比方 UI 事情,焦点事情,鼠标事情

215. 下列代码履行成果

Promise.resolve().then(() => {
    console.log(0);
    return Promise.resolve(4);
}).then((res) => {
    console.log(res)
})
Promise.resolve().then(() => {
    console.log(1);
}).then(() => {
    console.log(2);
}).then(() => {
    console.log(3);
}).then(() => {
    console.log(5);
}).then(() =>{
    console.log(6);
})

参考答案:

0 1 2 3 4 5 6

解析:

照着代码,咱们先来看初始使命。

  • (初始使命)榜首部分 Promise.resolve() 回来 「Promise { undefined }」。

  • (同使命,下同)继续调用 then,then 发现「Promise { undefined }」已处理,直接 enqueue 包括 console.log(0);return Promise.resolve(4) 的使命,之后回来新的「Promise { <pending> }」(设为 promise0)。被 enqueue 的使命之后会引发 promise0 的 resolve/reject,详见 追加使命一 的 2. 3. 。

  • 继续调用 promise0 上的 then,第二个 then 发现 promise0 还在 pending,因而不能直接 enqueue 新使命,而是将包括 console.log(res) 回调追加到 promise0 的 PromiseFulfillReactions 列表尾部,并回来新的「Promise { }」(设为 promiseRes)(该回来值在代码中被丢掉,但不影响整个进程)。

  • 第二部分 Promise.resolve().then… 同理,只需包括 console.log(1) 的使命被 enqueue。中心成果别离设为 promise1(=Promise.resolve().then(() => {console.log(1);})), promise2, promise3, promise5, promise6。当前使命履行完毕。

此刻,使命列队上有两个新使命,别离包括有 console.log(0);return Promise.resolve(4) 和 console.log(1) 。咱们用 「Job { ??? }」来指代。

接下来,「Job { console.log(0);return Promise.resolve(4) }」先被 enqueue,所以先运转「Job { console.log(0);return Promise.resolve(4) }」。

  • (追加使命一)此刻「0」被 console.log(0) 输出。Promise.resolve(4) 回来已处理的「Promise { 4 }」,然后 return Promise.resolve(4) 将这个「Promise { 4 }」作为最开端的 Promise.resolve().then(对应 promise0)的 onfulfill 处理程序(即 then(onfulfill, onreject) 的参数 onfulfill)的回来值回来。

  • (同使命,下同)onfulfill 处理程序回来,触发了 promise0 的 Promise Resolve Function(以下简称某 promise(实例)的 resolve)。所谓触发,其实是和其他东西一同打包到「Job { console.log(0);return Promise.resolve(4) }」傍边,按流程履行,onfulfill 回来后天然就到它了。(onfulfill 抛反常的话会被捕获并触发 reject,正常回来便是 resolve。)

  • promise0 的 resolve 查看 onfulfill 的回来值,发现该值包括可调用的「then」特色。这是当然的,由于是「Promise { 4 }」。不论该 Promise 实例是否处理,都将 enqueue 一个新使命包括调用该回来值的 then 的使命(即标准中的 NewPromiseResolveThenableJob(promiseToResolve, thenable, then))。而这个使命才会触发后续操作,在本例中,终究会将 promise0 的 PromiseFulfillReactions (其间有包括 console.log(res) 回调)再打包成使命 enqueue 到使命列队上。当前使命履行完毕。

此刻,使命列队上仍是有两个使命(一进一出),「Job { console.log(1) }」和「NewPromiseResolveThenableJob(promise0, 「Promise { 4 }」, 「Promise { 4 }」.then)」。接下来履行「Job { console.log(1) }」。

  • (追加使命二)「1」被输出。

  • (同使命,下同)onfulfill 处理程序回来 undefined。(JavaScript 的函数默许便是回来 undefined。)

  • promise1 的 resolve 发现 undefined 连 Object 都不是,天然不会有 then,所以将 undefined 作为 promise1 的处理成果。即 promise1 从「Promise { <pending> }」变为 「Promise { undefined }」(fulfill)。

  • resolve 继续查看 promise1 的 PromiseFulfillReactions。(reject 则会查看 PromiseRejectReactions。)有一个之前被 promise1.then 调用追加上的包括 console.log(2) 的回调。打包成使命入列。(如有多个则顺次第别离打包入列。)当前使命履行完毕。

此刻,使命列队上仍然有两个使命(一进一出)。「NewPromiseResolveThenableJob(…)」和 「Job { console.log(2) }」。履行「NewPromiseResolveThenableJob(…)」。

  • (追加使命三)调用 「Promise { 4 }」的 then。这个调用的参数(处理程序 onfulfill 和 onreject) 用的正是 promise0 的 resolve 和 reject。

  • 由于「Promise { 4 }」的 then 是标准的,行为和其他的 then 一致。(可拜见初始使命的进程 2. 。)它发现「Promise { 4 }」已处理,成果是 4。所以直接 enqueue 包括 promise0 的 resolve 的使命,参数是 4。理论上同样回来一个「Promise { }」,由于是在内部,不被外部调查,也不产生其他影响。)当前使命履行完毕。

此刻,使命列队上仍旧有两个使命(一进一出)。「Job { console.log(2) }」和 「Job { promise0 的 resolve }」。履行「Job { console.log(2) }」。

  • (追加使命四)进程相似「Job { console.log(1) }」的履行。「2」被输出。「Job { console.log(3) }」入列。其他不再赘述。当前使命履行完毕。

此刻,使命列队上依然有两个使命(一进一出)。「Job { promise0 的 resolve }」和「Job { console.log(3) }」。履行「Job { promise0 的 resolve }」。

  • (追加使命五)promise0 的 resolve 查看 PromiseFulfillReactions 发现有被 promise0.then 追加的回调。打包成使命入列。该使命包括 console.log(res),其间传递 promise0 处理成果 4 给参数 res。当前使命履行完毕。

此刻,使命列队上仍是两个使命(一进一出)。「Job { console.log(3) }」和「Job { console.log(res) }」。

  • (追加使命六)输出「3」。「Job { console.log(5) }」入列。

此刻,使命列队上仍是两个使命(一进一出)。「Job { console.log(res) }」和「Job { console.log(5) }」。

  • (追加使命七)输出「4」。由于 promiseRes 没有被 then 追加回调。就此打住。

此刻,使命列队上总算不再是两个使命了。下剩「Job { console.log(5) }」。

  • (追加使命八)输出「5」。「Job { console.log(6) }」入列。

终究一个使命(追加使命九)输出「6」。使命列队清空。

因而,输出的次序是「0 1 2 3 4 5 6」。

总结一下,除掉初始使命,总共 enqueue 了 9 个使命。其间,榜首串 Promise + then… enqueue 了 4 个。第二串 Promise + then… enqueue 了 5 个。剖析可知,每增加一个 then 就会增加一个使命入列。

而且,榜首串的 return Promise.resolve(4) 的写法额定 enqueue 了 2 个使命,别离在 promise0 的 resolve 时(追加使命一 3.)和调用「Promise { 4 }」的 then 本身时(追加使命三 2.)。

根据标准,它就该这样。说不上什么偶然,能够算是有意为之。处理程序里回来 thenable 方针就会导致增加两个使命入列。

216. 判别数组的办法,请别离介绍它们之间的差异和优劣

参考答案:

办法一:instanceof 操作符判别

用法:arr instanceof Array

instanceof 首要是用来判别某个实例是否归于某个方针

let arr = [];
console.log(arr instanceof Array); // true

缺陷:instanceof是判别类型的prototype是否呈现在方针的原型链中,可是方针的原型能够随意修正,所以这种判别并不精确。而且也不能判别方针和数组的差异

办法二:方针结构函数的 constructor判别

用法:arr.constructor === Array

Object的每个实例都有结构函数 constructor,用于保存着用于创立当前方针的函数

let arr = [];
console.log(arr.constructor === Array); // true

办法三:Array 原型链上的 isPrototypeOf

用法:Array.prototype.isPrototypeOf(arr)

Array.prototype 特色表明 Array 结构函数的原型

其间有一个办法是 isPrototypeOf() 用于测验一个方针是否存在于另一个方针的原型链上。

let arr = [];
console.log(Array.prototype.isPrototypeOf(arr)); // true

办法四:Object.getPrototypeOf

用法:Object.getPrototypeOf(arr) === Array.prototype

Object.getPrototypeOf() 办法回来指定方针的原型

所以只需跟Array的原型比较即可

let arr = [];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true

办法五:Object.prototype.toString

用法:Object.prototype.toString.call(arr) === ‘[object Array]’

尽管Array也承继自Object,但js在Array.prototype上重写了toString,而咱们经过toString.call(arr)实践上是经过原型链调用了。

let arr = [];
console.log(Object.prototype.toString.call(arr) === '[object Array]'); // true

缺陷:不能精准判别自界说方针,关于自界说方针只会回来[object Object]

办法六:Array.isArray

用法:Array.isArray(arr)

ES5中新增了Array.isArray办法,IE8及以下不支撑

Array.isArray ( arg ) isArray 函数需求一个参数 arg,假如参数是个方针而且 class 内部特色是 “Array”, 回来布尔值 true;不然它回来 false。

let arr = [];
console.log(Array.isArray(arr)); // true

缺陷:Array.isArray是ES 5.1推出的,不支撑IE6~8,所以在运用的时分需求注意兼容性问题。

217. JavaScript 中的数组和函数在内存中是怎么存储的?

参考答案:

JavaScript 中,数组不是以一段连续的区域存储在内存中,而是一种哈希映射的办法存储在堆内容里边。它能够经过多种数据结构完结,其间一种是链表。如下图所示:

2022高频前端面试题合集之JavaScript篇(下)

JavaScript 中的函数是存储在堆内存中的,详细的进程如下:

  1. 拓荒堆内存(16 进制得到内存地址)
  2. 声明当前函数的效果域(函数创立的上下文才是他的效果域,和在那履行的无关)
  3. 把函数的代码以字符串的办法存储在堆内存中(函数再不履行的情况下,仅仅存储在堆内存中的字符串)
  4. 将函数堆的地址,放在栈中供变量调用(函数名)

218. JavaScript 是怎么运转的?解说型言语和编译型言语的差异是什么?

参考答案:

关于榜首个问题,这不是三言两语或许几行文字就能够讲清楚的,这儿放上一篇博文地址:

segmentfault.com/a/119000001…

第二个问题:解说型言语和编译型言语的差异是什么?

电脑能认得的是二进制数,不能够辨认高档言语。一切高档言语在电脑上履行都需求先转变为机器言语。可是高档言语有两种类型:编译型言语和解说型言语。常见的编译型言言语语有C/C++、Pascal/Object 等等。常见的解说性言语有python、JavaScript等等。

编译型言语先要进行编译,然后转为特定的可履行文件,这个可履行文件是针对渠道的(CPU类型),能够这么了解你在PC上编译一个C源文件,需求经过预处理,编译,汇编等等进程生成一个可履行的二进制文件。当你需求再次运转改代码时,不需求从头编译代码,只需求运转该可履行的二进制文件。长处,编译一次,永久履行。还有一个长处是,你不需求供给你的源代码,你只需求发布你的可履行文件就能够为客户供给服务,然后保证了你的源代码的安全性。可是,假如你的代码需求迁移到linux、ARM下时,这时你的可履行文件就不起效果了,需求根据新的渠道编译出一个可履行的文件。这也便是多个渠道需求软件的多个版别。缺陷是,跨渠道能力差。

解说型言语需求一个解说器,在源代码履行的时分被解说器翻译为一个与渠道无关的中心代码,解说器会把这些代码翻译为及其言语。打个比方,编译型中的编译相当于一个翻译官,它只能翻译英语,而且中文文章翻译一次就不需求从头对文章进行二次翻译了,可是假如需求叫这个翻译官翻译德语就不行了。而解说型言语中的解说器相当于一个会各种言语的机器人,而且这个机器人回一句一句的翻译你的句子。关于不同的国家,翻译成不同的言语,所以,你只需求带着这个机器人就能够。解说型言语的有点是,跨渠道,缺陷是运转时需求源代码,知识产权保护性差,运转功率低。

219. 列举你所了解的编程范式?

参考答案:

编程范式 Programming paradigm 是指核算机中编程的典范办法或办法。

常见的编程范式有:函数式编程、程序编程、面向方针编程、指令式编程等。

不同的编程言语也会发起不同的“编程范型”。一些言语是专门为某个特定的范型规划的,如 SmalltalkJava 支撑面向方针编程。而 HaskellScheme 则支撑函数式编程。现代编程言语的开展趋势是支撑多种范型,例如 ES 支撑函数式编程的一起也支撑面向方针编程。

220. 什么是面向切面(AOP)的编程?

参考答案:

什么是AOP?

AOP(面向切面编程)的首要效果是把一些跟中心事务逻辑模块无关的功用抽离出来,这些跟事务逻辑无关的功用一般包括日志核算、安全操控、反常处理等。把这些功用抽离出来之后, 再经过“动态织入”的办法掺入事务逻辑模块中。

AOP能给咱们带来什么长处?

AOP的长处首要是能够保持事务逻辑模块的纯洁和高内聚性,其次是能够很方便地复用日志核算等功用模块。

JavaScript完结AOP的思路?

一般,在 JavaScript 中完结 AOP,都是指把一个函数“动态织入”到另外一个函数之中,详细的完结技能有许多,下面我用扩展 Function.prototype 来做到这一点。

首要便是两个函数,在Function的原型上加上before与after,效果便是字面的意思,在函数的前面或后边履行,相当于无侵入把一个函数刺进到另一个函数的前面或后边,运用妥当能够很好的完结代码的解耦,js中的代码完结如下:

//Aop结构器
function Aop(options){
    this.options = options
}
//事务办法履行前钩子
Aop.prototype.before = function(cb){
    cb.apply(this)
}
//事务办法履行后钩子
Aop.prototype.after = function(cb){
    cb.apply(this)
}
//事务办法履行器
Aop.prototype.execute = function(beforeCb,runner,afterCb){
    this.before(beforeCb)
    runner.apply(this)
    this.after(afterCb)
}
var aop = new Aop({
    afterInfo:'履行后',
    runnerInfo:'履行中',
    beforeInfo:'履行前'
})
var beforeCb = function(){
    console.log(this.options.beforeInfo)
}
var afterCb = function(){
    console.log(this.options.afterInfo)
}
var runnerCb = function(){
    console.log(this.options.runnerInfo)
}
aop.execute(beforeCb,runnerCb,afterCb)

运用的一些例子:

  1. window.onload 增加办法,防止 window.onload 被二次掩盖
  2. 无侵入核算某个函数的履行时间
  3. 表单校验
  4. 核算埋点
  5. 防止 csrf 进犯

221. JavaScript 中的 const 数组能够进行 push 操作吗?为什么?

参考答案:

能够进行 push 操作。尽管 const 表明常量,可是当咱们把一个数组赋值给 const 声明的变量时,实践上是把这个数组的地址赋值给该变量。而 push 操作是在数组地址所指向的堆区增加元素,地址本身并没有产生改动。

示例代码:

const arr = [1];
arr.push(2);
console.log(arr); // [1, 2]

222. JavaScript 中方针的特色描绘符有哪些?别离有什么效果?

参考答案:

ES5开端,增加了对方针特色描绘符的支撑。现在JavaScript中支撑 4 种特色描绘符:

  • configurable: 当且仅当该特色的configurable键值为true时,该特色的描绘符才干够被改动,一起该特色也能从对应的方针上被删去。
  • enumerable: 当且仅当该特色的enumerable键值为true时,该特色才会呈现在方针的枚举特色中。
  • value: 该特色对应的值。能够是任何有效的 JavaScript 值(数值,方针,函数等)。
  • writable: 当且仅当该特色的writable键值为true时,特色的值,也便是上面的value,才干被赋值运算符改动。

223. JavaScriptconsole 有哪些 api ?

参考答案:

console.assert(expression, object[, object…])

接纳至少两个参数,榜首个参数的值或回来值为false的时分,将会在操控台上输出后续参数的值。

console.count([label])

输出履行到该行的次数,可选参数 label 能够输出在次数之前。

console.dir(object)

将传入方针的特色,包括子方针的特色以列表办法输出。

console.error(object[, object…])

用于输出错误信息,用法和常见的console.log相同,不同点在于输出内容会标记为错误的样式,便于分辩。

console.group

这是个有趣的办法,它能够让操控台输出的句子产生不同的层级嵌套关系,每一个console.group()会增加一层嵌套,相反要减少一层嵌套能够运用console.groupEnd()办法。

console.info(object[, object…])

此办法与之前说到的console.error相同,用于输出信息,没有什么特别之处。

console.table()

可将传入的方针,或数组以表格办法输出,相比传统树形输出,这种输出计划更适合内部元素排列规整的方针或数组,不然可能会呈现许多的 undefined。

console.log(object[, object…])

输入一段 log 信息。

console.profile([profileLabel])

这是个挺高大上的东西,可用于性能剖析。在 JS 开发中,咱们常常要评估段代码或是某个函数的性能。在函数中手动打印时间固然能够,但显得不够灵活而且有差错。凭借操控台以及console.profile()办法咱们能够很方便地监控运转性能。

console.time(name) 计时器,能够将成对的console.time()console.timeEnd()之间代码的运转时间输出到操控台上,name参数可作为标签名。

console.trace()

console.trace()用来追寻函数的调用进程。在大型项目尤其是框架开发中,函数的调用轨道能够十分复杂,console.trace()办法能够将函数的被调用进程清楚地输出到操控台上。

console.warn(object[, object…])

输出参数的内容,作为正告提示。

225. Object.defineProperty 有哪几个参数?各自都有什么效果

参考答案:

JavaScript 中,经过 Object.defineProperty 办法能够设置方针特色的特性,选项如下:

  • get:一旦方针特色被拜访时,就会调用相应的办法
  • set:一旦方针特色被设置时,就会调用相应的办法
  • value:这是特色的值,默许是 undefined
  • writable:这是一个布尔值,表明一个特色是否能够被修正,默许是 true
  • enumerable:这是一个布尔值,表明在用 for-in 循环遍历方针的特色时,该特色是否能够显现出来,默许值为 true
  • configurable:这是一个布尔值,表明咱们是否能够删去一个特色或许修正特色的特性,默许值为 true

226. Object.definePropertyES6Proxy 有什么差异?

参考答案:

1、Object.defineproperty

能够用于监听方针的数据改变

语法: Object.defineproperty(obj, key, descriptor)

let obj = {
    age: 11
}
let value = 'xiaoxiao';
//defineproperty 有 gettter 和 setter
Object.defineproperty(obj, 'name', {
    get() {
        return value
    },
    set(newValue) {
        value = newValue
    }
})
obj.name = 'pengpeng';

此外 还有以下装备项 :

  • configurable
  • enumerable
  • value

缺陷:

  1. 无法监听数组改变

  2. 只能绑架方针的特色,特色值也是方针那么需求深度遍历

2、proxy :能够了解为在被绑架的方针之前 加了一层阻拦
let proxy = new Proxy({}, {
    get(obj, prop) {
        return obj[prop]
    },
    set(obj, prop, val) {
        obj[prop] = val
    }
})
  • proxy 回来的是一个新方针, 能够经过操作回来的新的方针到达意图
  • proxy 有多达 13 种阻拦办法

总结:

  • Object.defineProperty 无法监控到数组下标的改变,导致经过数组下标增加元素,不能实时呼应
  • Object.defineProperty 只能绑架方针的特色,然后需求对每个方针,每个特色进行遍历,假如,特色值是方针,还需求深度遍历。Proxy 能够绑架整个方针,并回来一个新的方针。
  • Proxy 不仅能够署理方针,还能够署理数组。还能够署理动态增加的特色。

227. intanceof 操作符的完结原理及完结

参考答案:

instanceof 首要效果便是判别一个实例是否归于某种类型

例如:

let Dog = function(){}
let tidy = new Dog()
tidy instanceof Dog //true

intanceof 操作符完结原理

function wonderFulInstanceOf(instance, constructorFn) {
    let constructorFnProto = constructorFn.prototype; // 取右表达式的 prototype 值,函数结构器指向的function 
    instanceProto = instance.__proto__; // 取左表达式的__proto__值,实例的__proto__
    while (true) {
    	if (instanceProto === null) {
            return false;	
        }
        if (instanceProto === constructorFnProto) {
            return true;	
        } 
        instanceProto = instanceProto.__proto__ 
    }
}

其实 instanceof 首要的完结原理便是只需 constructorFnprototypeinstance的原型链上即可。

因而,instanceof 在查找的进程中会遍历左面变量的原型链,直到找到右边变量的 prototype,假如查找失利,则会回来 false,告知咱们左面变量并非是右边变量的实例。

228. 强制类型转化规则?

参考答案:

首要需求了解隐式转化所调用的函数。

当程序员显式调用 Boolean(value)、Number(value)、String(value) 完结的类型转化,叫做显现类型转化。

当经过 new Boolean(value)、new Number(value)、new String(value) 传入各自对应的原始类型的值,能够完结“装箱”,将原始类型封装成一个方针。

其实这三个函数不仅仅能够当作结构函数,它们能够直接当作一般的函数来运用,将任何类型的参数转化成原始类型的值:

Boolean('sdfsd');  //  true
Number("23");  //  23
String({a:24});  //  "[object Object]"

其实这三个函数用于类型转化的时分,调用的便是 js 内部的 ToBoolean ( argument )、ToNumber ( argument )、ToString ( argument ) 办法,然后到达显式转化的效果。

229. Object.is( ) 与比较操作符 “===”、“==” 的差异

参考答案:

== (或许 !=) 操作在需求的情况下主动进行了类型转化。=== (或 !==)操作不会履行任何转化。

===在比较值和类型时,能够说比==更快。

而在ES6中,Object.is( ) 相似于 ===,但在三等号判等的基础上特别处理了 NaN 、-0 和 +0 ,保证 -0 和 +0 不再相同,但 Object.is(NaN, NaN) 会回来 true

230. + 操作符什么时分用于字符串的拼接?

参考答案:

在有一边操作数是字符串时会进行字符串拼接。

示例代码:

console.log(5 + '5', typeof (5 + '5')); // 55  string

231. object.assign 和扩展运算法是深仿制仍是浅仿制

参考答案:

这两个办法都是浅仿制。

在仿制的方针只需一层时是深仿制,可是一旦方针的特色值又是一个方针,也便是有两层或许两层以上时,就会发现这两种办法都是浅仿制。

233. 假如 new 一个箭头函数的会怎么样

参考答案:

会报错,由于箭头函数无法作为结构函数。

234. 扩展运算符的效果及运用场景

参考答案:

扩展运算符是三个点(…),首要用于展开数组,将一个数组转为参数序列。

扩展运算符运用场景:

  • 代替数组的 apply 办法
  • 兼并数组
  • 仿制数组
  • argumentsNodeList 转为数组
  • 与解构赋值结合运用
  • 将字符串转为数组

235. Proxy 能够完结什么功用?

参考答案:

ProxyES6 中新增的一个特性。Proxy 让咱们能够以简练易懂的办法操控外部对方针的拜访。其功用十分相似于规划办法中的署理办法。

Proxy 在方针方针的外层搭建了一层阻拦,外界对方针方针的某些操作,有必要经过这层阻拦。

运用 Proxy 的长处是方针只需重视于中心逻辑,一些非中心的逻辑(如:读取或设置方针的某些特色前记载日志;设置方针的某些特色值前,需求验证;某些特色的拜访操控等)能够让 Proxy 来做。然后到达重视点分离,降级方针复杂度的意图。

Proxy 的根本语法如下:

var proxy = new Proxy(target, handler);

经过结构函数来生成 Proxy 实例,结构函数接纳两个参数。target 参数是要阻拦的方针方针,handler 参数也是一个方针,用来定制阻拦行为。

Vue 3.0 首要就采用的 Proxy 特性来完结呼应式,相比以前的 Object.defineProperty 有以下长处:

  • 能够绑架整个方针,并回来一个新的方针
  • 13 种绑架操作

236. 方针与数组的解构的了解

参考答案:

解构是 ES6 的一种语法规则,能够将一个方针或数组的某个特色提取到某个变量中。

解构方针示例:

//  var/let/const{特色名}=被解构的方针
const user = {
    name: "abc",
    age: 18,
    sex: "男",
    address: {
        province: "重庆",
        city: "重庆"
    }
}
let { name, age, sex, address} = user;
console.log(name, age, sex, address);

解构数组示例:

const [a, b, c] = [1, 2, 3];

237. 怎么提取高度嵌套的方针里的指定特色?

参考答案:

一般会运用递归的办法来进行查找。下面是一段示例代码:

function findKey(data, field) {
    let finding = '';
    for (const key in data) {
        if (key === field) {
            finding = data[key];
        }
        if (typeof (data[key]) === 'object') {
            finding = findKey(data[key], field);
        }
        if (finding) {
            return finding;
        }
    }
    return null;
}
// 测验
console.log(findKey({
    name: 'zhangsan',
    age: 18,
    stuInfo: {
        stuNo: 1,
        classNo: 2,
        score: {
            htmlScore: 100,
            cssScore: 90,
            jsScore: 95
        }
    }
}, 'cssScore')); // 90

238. Unicode、UTF-8、UTF-16、UTF-32 的差异?

参考答案:

Unicode 为世界上一切字符都分配了一个仅有的数字编号,这个编号范围从 0x0000000x10FFFF (十六进制),有 110 多万,每个字符都有一个仅有的 Unicode 编号,这个编号一般写成 16 进制,在前面加上 U+。例如:“马”的 UnicodeU+9A6CUnicode 就相当于一张表,建立了字符与编号之间的联络。

2022高频前端面试题合集之JavaScript篇(下)

Unicode 本身只规则了每个字符的数字编号是多少,并没有规则这个编号怎么存储。

那咱们能够直接把 Unicode 编号直接转化成二进制进行存储,怎么对应到二进制表明呢?

Unicode 能够运用的编码有三种,别离是:

  • UFT-8:一种变长的编码计划,运用 1~6 个字节来存储;
  • UFT-32:一种固定长度的编码计划,不论字符编号巨细,一直运用 4 个字节来存储;
  • UTF-16:介于 UTF-8UTF-32 之间,运用 2 个或许 4 个字节来存储,长度既固定又可变。

239. 为什么函数的 arguments 参数是类数组而不是数组?怎么遍历类数组?

参考答案:

首要了解一下什么是数组方针和类数组方针。

数组方针:运用独自的变量名来存储一系列的值。从 Array 结构函数中承继了一些用于进行数组操作的办法。

例如:

var mycars = new Array();
mycars[0] = "zhangsan";
mycars[1] = "lisi";
mycars[2] = "wangwu";

类数组方针:关于一个一般的方针来说,假如它的一切 property 名均为正整数,一起也有相应的length特色,那么尽管该方针并不是由Array结构函数所创立的,它依然呈现出数组的行为,在这种情况下,这些方针被称为“类数组方针”。

两者差异

  • 一个是方针,一个是数组

  • 数组的length特色,当新的元素增加到列表中的时分,其值会主动更新。类数组方针的不会。

  • 设置数组的length特色能够扩展或截断数组。

  • 数组也是Array的实例能够调用Array的办法,比方push、pop等等

所以说arguments方针不是一个 Array 。它相似于Array,但除了length特色和索引元素之外没有任何Array特色。

能够运用 for…in 来遍历 arguments 这个类数组方针。

240. escape、encodeURI、encodeURIComponent 的差异

参考答案:

escape 除了 ASCII 字母、数字和特定的符号外,对传进来的字符串悉数进行转义编码,因而假如想对 URL 编码,最好不要运用此办法。

encodeURI 用于编码整个 URI,由于 URI 中的合法字符都不会被编码转化。

encodeURIComponent 办法在编码单个URIComponent(指恳求参数)应当是最常用的,它能够讲参数中的中文、特别字符进行转义,而不会影响整个 URL

241. use strict 是什么意思 ? 运用它差异是什么?

参考答案:

use strict 代表敞开严厉办法,这种办法使得 Javascript 在更严厉的条件下运转,实行更严厉解析和错误处理。

敞开“严厉办法”的长处:

  • 消除 Javascript 语法的一些不合理、不严谨之处,减少一些奇怪行为;
  • 消除代码运转的一些不安全之处,保证代码运转的安全;
  • 提高编译器功率,增加运转速度;
  • 为未来新版别的 Javascript 做好铺垫。

242. for…infor…of 的差异

参考答案:

JavaScript 原有的 for…in 循环,只能取得方针的键名,不能直接获取键值。ES6 供给 for…of 循环,答应遍历取得键值。

例如:

var arr = ['a', 'b', 'c', 'd'];
for (let a in arr) {
  console.log(a); // 0 1 2 3
}
for (let a of arr) {
  console.log(a); // a b c d
}

243. ajax、axios、fetch 的差异

参考答案:

ajax 是指一种创立交互式网页运用的网页开发技能,而且能够做到无需从头加载整个网页的情况下,能够更新部分网页,也叫作局部更新。

运用 ajax 发送恳求是依靠于一个方针,叫 XmlHttpRequest 方针,经过这个方针咱们能够从服务器获取到数据,然后再烘托到咱们的页面上。现在简直一切的浏览器都有这个方针,只需 IE7 以下的没有,而是经过 ActiveXObject 这个方针来创立的。

Fetchajax 十分好的一个替代品,根据 Promise 规划,运用 Fetch 来获取数据时,会回来给咱们一个 Pormise 方针,可是 Fetch 是一个低层次的 API,想要很好的运用 Fetch,需求做一些封装处理。

下面是 Fetch 的一些缺陷

  • Fetch 只对网络恳求报错,对 400,500 都作为成功的恳求,需求封装去处理
  • Fetch 默许不会带 cookie,需求增加装备项。
  • Fetch 不支撑 abort,不支撑超时操控,运用 setTimeoutPromise.reject 的完结超时操控并不能阻挠恳求进程继续在后台运转,造成了流量的浪费。
  • Fetch 没有办法原生监测恳求的进展,而 XHR 能够。

Vue2.0 之后,axios 开端遭到更多的欢迎了。其实 axios 也是对原生 XHR 的一种封装,不过是 Promise 完结版别。它能够用于浏览器和 nodejsHTTP 客户端,契合最新的 ES 标准。

244. 下面代码的输出是什么?( D

function sayHi() {
  console.log(name);
  console.log(age);
  var name = "Lydia";
  let age = 21;
}
sayHi();
  • A: Lydiaundefined
  • B: LydiaReferenceError
  • C: ReferenceError21
  • D: undefinedReferenceError

剖析:

sayHi 函数内部,经过 var 声明的变量 name 会产生变量提高,var name 会提高到函数效果域的顶部,其默许值为 undefined。因而输出 name 时得到的值为 undefined

let 声明的 age 不会产生变量提高,在输出 age 时该变量还未声明,因而会抛出 ReferenceError 的报错。

245. 下面代码的输出是什么?( C

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}
  • A: 0 1 20 1 2
  • B: 0 1 23 3 3
  • C: 3 3 30 1 2

剖析:

JavaScript 中的履行机制,setTimeout 为异步代码,因而在 setTimeout 履行时,for 循环现已履行完毕。

榜首个 for 循环中的变量 i 经过 var 声明, 为大局变量,因而每一次的 i++ 都会将大局变量 i 的值加 1,当榜首个 for 履行完结后 i 的值为 3。所以再履行 setTimeout 时,输出 i 的值都为 3

第二个 for 循环中的变量 i 经过 let 声明,为局部变量,因而每一次 for 循环时都会产生一个块级效果域,用来存储本次循环中新产生的 i 的值。当循环完毕后,setTimeout 会沿着效果域链去对应的块级效果域中寻觅对应的 i 值。

246. 下面代码的输出是什么?( B

const shape = {
  radius: 10,
  diameter() {
    return this.radius * 2;
  },
  perimeter: () => 2 * Math.PI * this.radius
};
shape.diameter();
shape.perimeter();
  • A: 2062.83185307179586
  • B: 20NaN
  • C: 2063
  • D: NaN63

剖析:

diameter 作为方针的办法,其内部的 this 指向调用该办法的方针,因而 this.raduus 获取到的是 shape.radius 的值 10,再乘以 2 输出的值即为 20

perimeter 是一个箭头函数,其内部的 this 应该承继声明时地点上下文中的 this,在这儿即承继大局的 this,因而 this.radius 值的为 undefinedundefined 与数值相乘后值为 NaN

247. 下面代码的输出是什么?( A

+true;
!"Lydia";
  • A: 1false
  • B: falseNaN
  • C: falsefalse

剖析:

一元加号会将数据隐式转化为 number 类型,true 转化为数值为 1

非运算符 ! 会将数据隐式转化为 boolean 类型后进行取反,“Lydia” 转化为布尔值为 true,取反后为 false

248. 哪个选项是不正确的?( A

const bird = {
  size: "small"
};
const mouse = {
  name: "Mickey",
  small: true
};
  • A: mouse.bird.size
  • B: mouse[bird.size]
  • C: mouse[bird[“size”]]
  • D: 以上选项都对

剖析:

mouse 方针中没有 bird 特色,当拜访一个方针不存在的特色时值为 undefined,因而 mouse.bird 的值为 undefined,而 undefined 作为原始数据类型没有 size 特色,因而再拜访 undefined.size 时会报错。

249. 下面代码的输出是什么?( A

let c = { greeting: "Hey!" };
let d;
d = c;
c.greeting = "Hello";
console.log(d.greeting);
  • A: Hello
  • B: undefined
  • C: ReferenceError
  • D: TypeError

剖析:

JavaScript 中,复杂类型数据在进行赋值操作时,进行的是「引证传递」,因而变量 dc 指向的是同一个引证。当 c 经过引证去修正了数据后,d 再经过引证去拜访数据,获取到的实践便是 c 修正后的数据。

250. 下面代码的输出是什么?( C

let a = 3;
let b = new Number(3);
let c = 3;
console.log(a == b);
console.log(a === b);
console.log(b === c);
  • A: true false true
  • B: false false true
  • C: true false false
  • D: false true true

剖析:

new Number()JavaScript 中一个内置的结构函数。变量 b 尽管看起来像一个数字,但它并不是一个真正的数字:它有一堆额定的功用,是一个方针。

== 会触发隐式类型转化,右侧的方针类型会主动转化为 Number 类型,因而终究回来 true

=== 不会触发隐式类型转化,因而在比较时由于数据类型不持平而回来 false

251. 下面代码的输出是什么?( D

class Chameleon {
  static colorChange(newColor) {
    this.newColor = newColor;
  }
  constructor({ newColor = "green" } = {}) {
    this.newColor = newColor;
  }
}
const freddie = new Chameleon({ newColor: "purple" });
freddie.colorChange("orange");
  • A: orange
  • B: purple
  • C: green
  • D: TypeError

剖析

colorChange 办法是静态的。 静态办法仅在创立它们的结构函数中存在,而且不能传递给任何子级。 由于 freddie 是一个子级方针,函数不会传递,所以在 freddie 实例上不存在 colorChange 办法:抛出TypeError

252. 下面代码的输出是什么?( A

let greeting;
greetign = {}; // Typo!
console.log(greetign);
  • A: {}
  • B: ReferenceError: greetign is not defined
  • C: undefined

剖析:

操控台会输出空方针,由于咱们刚刚在大局方针上创立了一个空方针!

当咱们错误地将 greeting 输入为 greetign 时,JS 解说器实践上在浏览器中将其视为 window.greetign = {}

253. 当咱们履行以下代码时会产生什么?( A

function bark() {
console.log("Woof!");
}
bark.animal = "dog";
  • A 什么都不会产生
  • B: SyntaxError. You cannot add properties to a function this way.
  • C: undefined
  • D: ReferenceError

剖析:

由于函数也是方针!(原始类型之外的一切东西都是方针)

函数是一种特别类型的方针,咱们能够给函数增加特色,且此特色是可调用的。

254. 下面代码的输出是什么?( A

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}
const member = new Person("Lydia", "Hallie");
Person.getFullName = () => this.firstName + this.lastName;
console.log(member.getFullName());
  • A: TypeError
  • B: SyntaxError
  • C: Lydia Hallie
  • D: undefined undefined

剖析:

Person.getFullName 是将办法增加到了函数身上,因而当咱们经过实例方针 member 去调用该办法时并不能找到该办法。

255. 下面代码的输出是什么?( A

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}
const lydia = new Person("Lydia", "Hallie");
const sarah = Person("Sarah", "Smith");
console.log(lydia);
console.log(sarah);
  • A: Person { firstName: “Lydia”, lastName: “Hallie” }undefined
  • B: Person { firstName: “Lydia”, lastName: “Hallie” }Person { firstName: “Sarah”, lastName: “Smith” }
  • C: Person { firstName: “Lydia”, lastName: “Hallie” }{}
  • D: Person { firstName: “Lydia”, lastName: “Hallie” }ReferenceError

剖析:

lydia 是调用结构函数后得到的实例方针,拥有 firstNamelastName 特色;

sarah 是调用一般函数后得到的回来值,而 Person 作为一般函数没有回来值;

256. 事情传达的三个阶段是什么?( D

  • A: 方针 > 捕获 > 冒泡
  • B: 冒泡 > 方针 > 捕获
  • C: 方针 > 冒泡 > 捕获
  • D: 捕获 > 方针 > 冒泡

257. 下面代码的输出是什么?( C

function sum(a, b) {
  return a + b;
}
sum(1, "2");
  • A: NaN
  • B: TypeError
  • C: “12”
  • D: 3

剖析:

任意数据类型在跟 String 做 + 运算时,都会隐式转化为 String 类型。

a 所对应的 Number1,被隐式转化为了 String 值 “1”,终究字符串拼接的到 “12”。

258. 下面代码的输出是什么?( C

let number = 0;
console.log(number++);
console.log(++number);
console.log(number);
  • A: 1 1 2
  • B: 1 2 2
  • C: 0 2 2
  • D: 0 1 2

剖析:

++ 后置时,先输出,后加 1;++ 前置时,先加 1,后输出;

榜首次输出的值为 0,输出完结后 number1 变为 1

第2次输出,number 先加 1 变为 2,然后输出值 2

第三次输出,number 值没有改变,仍是 2

259. 下面代码的输出是什么?( B

function getPersonInfo(one, two, three) {
  console.log(one);
  console.log(two);
  console.log(three);
}
const person = "Lydia";
const age = 21;
getPersonInfo`${person} is ${age} years old`;
  • A: Lydia 21 [“”, “is”, “years old”]
  • B: [“”, “is”, “years old”] Lydia 21
  • C: Lydia [“”, “is”, “years old”] 21

剖析:

假如运用标记的模板字符串,则榜首个参数的值一直是字符串值的数组。 其他参数获取传递到模板字符串中的表达式的值!

260. 下面代码的输出是什么?( C

function checkAge(data) {
  if (data === { age: 18 }) {
    console.log("You are an adult!");
  } else if (data == { age: 18 }) {
    console.log("You are still an adult.");
  } else {
    console.log(`Hmm.. You don't have an age I guess`);
  }
}
checkAge({ age: 18 });
  • A: You are an adult!
  • B: You are still an adult.
  • C: Hmm.. You don’t have an age I guess

剖析:

在比较持平性时,原始类型经过它们的值进行比较,而方针经过它们的引证进行比较。

data 和条件中的 { age: 18 } 两个不同引证的方针,因而永久都不持平。

261. 下面代码的输出是什么?( C

function getAge(...args) {
  console.log(typeof args);
}
getAge(21);
  • A: “number”
  • B: “array”
  • C: “object”
  • D: “NaN”

剖析:

ES6 中的不定参数(…args)回来的是一个数组。

typeof 查看数组的类型回来的值是 object

262. 下面代码的输出是什么?( C

function getAge() {
  "use strict";
  age = 21;
  console.log(age);
}
getAge();
  • A: 21
  • B: undefined
  • C: ReferenceError
  • D: TypeError

剖析:

“use strict” 严厉办法中,运用未声明的变量会引发报错。

263. 下面代码的输出是什么?( A

const sum = eval("10*10+5");
  • A: 105
  • B: “105”
  • C: TypeError
  • D: “10*10+5”

剖析:

eval 办法会将字符串当作 JavaScript 代码进行解析。

264. cool_secret 能够拜访多长时间?( B

sessionStorage.setItem("cool_secret", 123);
  • A:永久,数据不会丢失。
  • B:用户封闭选项卡时。
  • C:当用户封闭整个浏览器时,不仅是选项卡。
  • D:用户封闭核算机时。

剖析:

sessionStorage 是会话级其他本地存储,当窗口封闭,则会话完毕,数据删去。

265. 下面代码的输出是什么?( B

var num = 8;
var num = 10;
console.log(num);
  • A: 8
  • B: 10
  • C: SyntaxError
  • D: ReferenceError

剖析:

var 声明的变量答应重复声明,但后边的值会掩盖前面的值。

266. 下面代码的输出是什么?( C

const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);
obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1);
  • A: false true false true
  • B: false true true true
  • C: true true false true
  • D: true true true true

267. 下面代码的输出是什么?( C

const obj = { a: "one", b: "two", a: "three" };
console.log(obj);
  • A: { a: “one”, b: “two” }
  • B: { b: “two”, a: “three” }
  • C: { a: “three”, b: “two” }
  • D: SyntaxError

剖析:

假如方针有两个具有相同名称的键,则后边的将替前面的键。它仍将处于榜首个方位,但具有终究指定的值。

268. 下面代码的输出是什么?( C

for (let i = 1; i < 5; i++) {
  if (i === 3) continue;
  console.log(i);
}
  • A: 1 2
  • B: 1 2 3
  • C: 1 2 4
  • D: 1 3 4

剖析:

i 的值为 3 时,进入 if 句子履行 continue,完毕本次循环,当即进行下一次循环。

269. 下面代码的输出是什么?( A

String.prototype.giveLydiaPizza = () => {
  return "Just give Lydia pizza already!";
};
const name = "Lydia";
name.giveLydiaPizza();
  • A: “Just give Lydia pizza already!”
  • B: TypeError: not a function
  • C: SyntaxError
  • D: undefined

剖析:

String 是一个内置的结构函数,咱们能够为它增加特色。 咱们给它的原型增加了一个办法。 原始类型的字符串主动转化为字符串方针,由字符串原型函数生成。 因而,一切字符串(字符串方针)都能够拜访该办法!

当运用根本类型的字符串调用 giveLydiaPizza 时,实践上产生了下面的进程:

  • 创立一个 String 的包装类型实例
  • 在实例上调用 substring 办法
  • 销毁实例

270. 下面代码的输出是什么?( B

const a = {};
const b = { key: "b" };
const c = { key: "c" };
a[b] = 123;
a[c] = 456;
console.log(a[b]);
  • A: 123
  • B: 456
  • C: undefined
  • D: ReferenceError

剖析:

bc 作为一个方针的键时,会主动转化为字符串,而方针主动转化为字符串化时,成果都为 [Object object]。因而 a[b]a[c] 其实都是同一个特色 a[“Object object”]

方针同名的特色后边的值会掩盖前面的,因而终究 a[“Object object”] 的值为 456

271. 下面代码的输出是什么?( B

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"));
const baz = () => console.log("Third");
bar();
foo();
baz();
  • A: First Second Third
  • B: First Third Second
  • C: Second First Third
  • D: Second Third First

剖析:

bar 函数中履行的是一段异步代码,依照 JavaScript 中的事情循环机制,主线程中的一切同步代码履行完结后才会履行异步代码。因而 “Second” 终究输出。

272. 单击按钮时 event.target 是什么?( C

<div onclick="console.log('first div')">
  <div onclick="console.log('second div')">
    <button onclick="console.log('button')">
      Click!
    </button>
  </div>
</div>
  • A: div 外部
  • B: div 内部
  • C: button
  • D: 一切嵌套元素的数组

剖析:

event.target 指向的是事情方针,即触发事情的元素。因而点击 <button> 触发事情的也便是 <button>

273. 单击下面的 html 片段打印的内容是什么?( A

<div onclick="console.log('div')">
  <p onclick="console.log('p')">
    Click here!
  </p>
</div>
  • A: p div
  • B: div p
  • C: p
  • D: div

剖析:

onclick 绑定的事情为冒泡型事情。因而当点击 p 标签时,事情会从事情方针开端顺次往外触发。

274. 下面代码的输出是什么?( D

const person = { name: "Lydia" };
function sayHi(age) {
  console.log(`${this.name} is ${age}`);
}
sayHi.call(person, 21);
sayHi.bind(person, 21);
  • A: undefined is 21 Lydia is 21
  • B: function function
  • C: Lydia is 21 Lydia is 21
  • D: Lydia is 21 function

剖析:

callbind 都能够修正 this 的指向,但差异在于 call 办法会当即履行,而 bind 会回来一个修正后的新函数。

275. 下面代码的输出是什么?( B

function sayHi() {
  return (() => 0)();
}
typeof sayHi();
  • A: “object”
  • B: “number”
  • C: “function”
  • D: “undefined”

剖析:

return 后是一个 IIFE,其回来值是 0,因而 sayHi 函数中回来的是一个 0typeof 检测 sayHi 回来值类型即为 number

276. 下面这些值哪些是假值?( A

0;
new Number(0);
("");
(" ");
new Boolean(false);
undefined;
  • A: 0 “” undefined
  • B: 0 new Number(0) “” new Boolean(false) undefined
  • C: 0 “” new Boolean(false) undefined
  • D: 一切都是假值。

剖析:

JavaScript 中假值只需 6 个:false“”nullundefinedNaN0

278. 下面代码的输出是什么?( B

console.log(typeof typeof 1);
  • A: “number”
  • B: “string”
  • C: “object”
  • D: “undefined”

剖析:

typeof 1 回来 “number”typeof “number” 回来 “string”

279. 下面代码的输出是什么?( C

const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);
  • A: [1, 2, 3, 7 x null, 11]
  • B: [1, 2, 3, 11]
  • C: [1, 2, 3, 7 x empty, 11]
  • D: SyntaxError

剖析:

当你为数组中的元素设置一个超越数组长度的值时,JavaScript 会创立一个名为“空插槽”的东西。 这些方位的值实践上是 undefined,但你会看到相似的东西:

[1, 2, 3, 7 x empty, 11]

这取决于你运转它的方位(每个浏览器有可能不同)。

280. 下面代码的输出是什么?( A

(() => {
  let x, y;
  try {
    throw new Error();
  } catch (x) {
    (x = 1), (y = 2);
    console.log(x);
  }
  console.log(x);
  console.log(y);
})();
  • A: 1 undefined 2
  • B: undefined undefined undefined
  • C: 1 1 2
  • D: 1 undefined undefined

剖析:

catch 块接纳参数 x。当咱们传递参数时,这与变量的 x 不同。这个变量 x 是归于 catch 效果域的。

之后,咱们将这个块级效果域的变量设置为 1,并设置变量 y 的值。 现在,咱们打印块级效果域的变量 x,它等于 1

catch 块之外,x 仍然是 undefined,而 y2。 当咱们想在 catch 块之外的 console.log(x) 时,它回来undefined,而 y 回来 2

281. JavaScript 中的一切内容都是…( A

  • A:原始或方针
  • B:函数或方针
  • C:技巧问题!只需方针
  • D:数字或方针

剖析:

JavaScript 只需原始类型和方针。

282. 下面代码的输出是什么?

[[0, 1], [2, 3]].reduce(
  (acc, cur) => {
    return acc.concat(cur);
  },
  [1, 2]
);
  • A: [0, 1, 2, 3, 1, 2]
  • B: [6, 1, 2]
  • C: [1, 2, 0, 1, 2, 3]
  • D: [1, 2, 6]

剖析:

[1,2] 是咱们的初始值。 这是咱们开端履行 reduce 函数的初始值,以及榜首个 acc 的值。 在榜首轮中,acc[1,2]cur[0,1]。 咱们将它们连接起来,成果是 [1,2,0,1]

然后,acc 的值为 [1,2,0,1]cur 的值为 [2,3]。 咱们将它们连接起来,得到 [1,2,0,1,2,3]

283. 下面代码的输出是什么?( B

!!null;
!!"";
!!1;
  • A: false true false
  • B: false false true
  • C: false true true
  • D: true true false

剖析:

null 是假值。 !null 回来 true!true 回来 false

“” 是假值。 !”” 回来 true!true 回来 false

1 是真值。 !1 回来 false!false 回来 true

284. setInterval 办法的回来值什么?( A

setInterval(() => console.log("Hi"), 1000);
  • A:一个仅有的 id
  • B:指定的毫秒数
  • C:传递的函数
  • D:undefined

剖析:

它回来一个仅有的 id。 此 id 可用于运用 clearInterval() 函数清除该定时器。

285. 下面代码的回来值是什么?( A

[..."Lydia"];
  • A: [“L”, “y”, “d”, “i”, “a”]
  • B: [“Lydia”]
  • C: [[], “Lydia”]
  • D: [[“L”, “y”, “d”, “i”, “a”]]

剖析:

字符串是可迭代的。 扩展运算符将迭代的每个字符映射到一个元素。

286. document.writeinnerHTML 有哪些差异?

参考答案:

document.writeinnerHTML 都能将 HTML 字符串解析为 DOM 树,再将 DOM 树刺进到某个方位,但两种在履行细节上仍是有许多不同。

1)write() 办法存在于 Document 方针中,innerHTML 特色存在于 Element 方针中;

2)document.write 会将解析后的 DOM 树刺进到文档中调用它的脚本元素的方位,而 innerHTML 会将 DOM 树刺进到指定的元素内;

3)document.write 会将屡次调用的字符串参数主动连接起来,innerHTML 要用赋值运算符 “+=” 拼接;

4)只需当文档还在解析时,才干运用 document.write,不然 document.write 的值会将当前文档掩盖掉,而 innerHTML 特色则没有这个限制;

注:也能够参看前面第 157 题答案

287. 假设有两个变量 ab,他们的值都是数字,怎么在不借用第三个变量的情况下,将两个变量的值对调?

参考答案:

办法一:

a = a + b;
b = a - b;
a = a - b; 

办法二(ES6 中的解构):

[a, b] = [b, a]

288. 前端为什么发起模块化开发?

参考答案:

模块化能将一个复杂的大型体系分解成一个个高内聚、低耦合的简略模块,而且每个模块都是独立的,用于完结特定的功用。模块化后的体系变得更加可控、可保护、可扩展,程序代码也更简略直观,可读性也很高,有利于团队协作开发。ES6 模块化的呈现,使得前端能更简单、更快速的完结模块化开发。

289. 请解说 JSONP 的原理,并用代码描绘其进程。

参考答案:

*JSONP(JSON with padding)*是一种凭借 <script> 元素完结跨域的技能,它不会运用 XHR 方针。之所以能完结跨域,首要是由于 <script> 元素有以下两个特色:

1)它的 src 特色能够拜访任何 URL 资源,不会受同源战略的限制;

2)假如拜访的资源包括 JavaScript 代码,那么在下载下来后会主动履行;

JSONP 便是根据这两点,再与服务器合作来完结跨域恳求的,它的履行进程可分为以下 6 步:

1)界说一个回调函数;

2)用 DOM 办法动态创立一个 <script> 元素;

3)经过 <script> 元素的 src 特色指定要恳求的 URL,而且将回调函数的名称作为一个参数传递过去;

4)将 <script> 元素刺进到当前文档中,开端恳求;

5)服务器接纳到传递过来的参数,然后将回调函数和数据以调用的办法输出;

6)当 <script> 元素接纳到呼应中的脚本代码后,就会主动的履行它们;

290. 列举几种 JavaScript 中数据类型的强制转化和隐式转化。

参考答案:

强制转化:

  • 转化为 numberparseInt()parseFloat()Number()
  • 转化为 stringString()toString()
  • 转化为 booleanBoolean()

隐式转化:

  • 隐式转化为 number:算术运算/比较运算,例如加、减、乘、除、持平(==)、大于、小于等;
  • 隐式转化为 string:与字符串拼接,例如 + “”;
  • 隐式转化为 boolean:逻辑运算,例如或(||)、与(&&)、非(!);

291. 剖析以下代码的履行成果并解说为什么。

var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x) 	
console.log(b.x)

参考答案:

运转成果:

undefined{n: 2}

剖析:

首要,ab 一起引证了 {n: 1} 方针,接着履行到 a.x = a = {n: 2} 句子,尽管赋值是从右到左履行,可是点(.)的优先级比赋值符(=)要高,所以这儿首要履行 a.x,相当于为 a(或许 b)所指向的 {n:1} 方针新增了一个特色 x,即此刻方针将变为 {n: 1; x: undefined}。然后按正常情况,从右到左进行赋值,此刻履行 a = {n: 2} 的时分,a的引证改动,指向了新方针 {n: 2},而 b 依然指向的是旧方针 {n: 1; x: undefined}。之后再履行 a.x = {n: 2} 的时分,并不会从头解析一遍 a,而是沿袭开始解析 a.x 时分的 a,即旧方针 {n: 1; x: undefined},故此刻旧方针的 x 的值变为*{n: 2}*,旧方针为 {n: 1; x: {n: 2}},它依然被 b 引证着。

终究,a 指向的方针为 {n: 2}b 指向的方针为 {n: 1; x: {n: 2}}。因而输出 a.x 值为 undefined,输出 b.x 值为 {n: 2}

292. 剖析以下代码的履行成果并解说为什么。

// example 1
var a = {}, b = '123', c = 123;  
a[b] = 'b';
a[c] = 'c';  
console.log(a[b]);
// example 2
var a = {}, b = Symbol('123'), c = Symbol('123');  
a[b] = 'b';
a[c] = 'c';  
console.log(a[b]);
// example 3
var a = {}, b = {key:'123'}, c = {key:'456'};  
a[b] = 'b';
a[c] = 'c';  
console.log(a[b]);

参考答案:

运转成果:

example 1c

example 2b

example 3c

剖析:

这题调查的是方针的键名的转化。

  • 方针的键名只能是字符串和 Symbol 类型。
  • 其他类型的键名会被转化成字符串类型。
  • 方针转字符串默许会调用 String 办法。

因而 example 1c 作为键名后也是 ‘123’,直接掩盖 a[b] 的值;而 example 2 中,Symbol 作为 ES6 中新增的根本数据类型,它的特色便是仅有,Symbol() 办法生成的值都是仅有的,里边的参数不会影响成果。因而在 example 2bc 是两个不同的键名;example 3 中,方针不能作为键名,因而 bc 都会经过 String() 办法转为字符串 [object Object]

293. 下面的代码打印什么内容?为什么?

var b = 10;
(function b() {
  b = 20;
  console.log(b)
})()

参考答案:

运转成果:

function b() { b = 20; console.log(b) } 剖析:

JavaScript 解说器遇到非匿名当即履行函数(标题中的 b)时,会创立一个辅助的特定方针,然后将函数名称当作这个方针的特色,因而函数内部能够拜访到 b,可是这个值又是只读的,所以对他的赋值并不收效,所以打印的成果仍是这个函数,而且外部的值也没有产生更改。

294. 下面代码中,a 在什么情况下会履行输出句子打印 1

var a = ?;
if(a == 1 && a == 2 && a == 3){
 	console.log(1);
}

参考答案:

剖析:

这道题考查的知识点是:持平运算符(==)在作比较时会进行隐式转化,而假如操作数是引证类型,则会调用 toString()valueOf() 办法对引证类型数据进行隐式转化。

// 办法一:运用 toString()
let a = {
  i: 1,
  toString () {
    return a.i++;
  }
}
if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}
// 办法二:运用 valueOf()
let a = {
  i: 1,
  valueOf () {
    return a.i++
  }
}
if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}
// 办法三:运用数组(这个是真的骚)
var a = [1,2,3];
a.join = a.shift;
if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}
// 办法四:运用 Symbol
let a = {[Symbol.toPrimitive]: ((i) => () => ++i) (0)};
if(a == 1 && a == 2 && a == 3) {
  console.log('1');
}

办法一和办法二没啥解说的了,解说下办法三和办法四。

办法三:

a.join = a.shift 的意图是将数组的 join 办法替换成 shift 办法。由于数组在参加持平比较时也会经过 toString() 将数组转为字符串,而该字符串实践上是数组中每个元素的 toString() 回来值经调用 join() 办法拼接(由逗号离隔)组成。现在咱们将 join() 办法替换为了 shift() 办法,也就意味着数组在经过 toString() 隐式转化后,得到是 shift() 的回来值,每次回来数组中的榜首个元素,而原数组删去榜首个值,正好能够使判别成立。

办法四:

ES6 中供给了 11 个内置的 Symbo 值,指向言语内部运用的办法。Symbol.toPrimitive 便是其间一个,它指向一个办法,当该方针被转为原始类型的值时,会调用这个办法,并回来该方针对应的原始类型值。这儿便是改动这个特色,把它的值改为一个闭包回来的函数。

295. 介绍前端模块化的开展。

参考答案:

  • IIFE:运用自履行函数来编写模块化(特色:在一个独自的函数效果域中履行代码,防止变量抵触)。

    (function(){
      return { data:[] }
    })()
    
  • AMD:运用 requireJS 来编写模块化(特色:依赖有必要提前声明好)。

    define('./index.js',function(code){
    	// code 便是index.js 回来的内容
    })
    
  • CMD:运用 seaJS 来编写模块化(特色:支撑动态引进依赖文件)。

    define(function(require, exports, module) {
      var indexCode = require('./index.js');
    });
    
  • CommonJSnodejs 中自带的模块化。

    var fs = require('fs');
    
  • UMD:通用模块标准,整合了 AMDCommonJS 模块化。

    (function (global, factory) {
      if (typeof exports === 'object' && typeof module !== undefined) { //查看CommonJS是否可用
        module.exports = factory(require('jquery'));
      } else if (typeof define === 'function' && define.amd) {      //查看AMD是否可用
        define('toggler', ['jquery', factory])
      } else {       //两种都不能用,把模块增加到JavaScript的大局命名空间中。
        global.toggler = factory(global, factory);
      }
    })(this, function ($) {
      function init() {
      }
      return {
        init: init
      }
    });
    
  • webpack(require.ensure)webpack 2.x 版别中的代码切割。

  • ES ModulesES6 引进的模块化,支撑 import 来引进另一个 js

296. 请指出 document.onload 和 document.ready 两个事情的差异

参考答案:

页面加载完结有两种事情:一是 ready,表明文档结构现已加载完结(不包括图片等非文字媒体文件);二是 onload,指示页面包括图片等文件在内的一切元素都加载完结。

297. 表单元素的readonlydisabled 两个特色有什么差异?

参考答案:

  • readonly
    • 不行修改,但能够挑选和仿制;
    • 值能够传递到后台;
  • disabled:
    • 不能修改,不能仿制,不能挑选;
    • 值不能够传递到后台;

298. 列举几种你知道的数组排序的办法。

参考答案:

// 办法一:挑选排序
let ary = [5, 7, 8, 11, 3, 6, 4];
for (let i = 0; i < ary.length - 1; i++) {
  for (let j = i + 1; j < ary.length; j++) {
    if (ary[i] < ary[j]) {
      [ary[i], ary[j]] = [ary[j], ary[i]];
    }
  }
}
// 办法二:冒泡排序
let ary = [5, 7, 8, 11, 3, 6, 4];
for (let i = 1; i < ary.length; i++) { 
  for (let j = 0; j < ary.length - i; j++) {  
    if (ary[j] < ary[j + 1]) {
      [ary[j], ary[j + 1]] = [ary[j + 1], ary[j]]
    }
  }
}

299. 区别什么是“客户区坐标”、“页面坐标”、“屏幕坐标”?

参考答案:

  • 客户区坐标:鼠标指针在可视区中的水平坐标 (clientX) 和垂直坐标 (clientY);
  • 页面坐标:鼠标指针在页面布局中的水平坐标 (pageX) 和垂直坐标 (pageY);
  • 屏幕坐标:设备物理屏幕的水平坐标 (screenX) 和垂直坐标 (screenY);

300. 怎么编写高性能的 JavaScript

参考答案:

  • 遵从严厉办法:”use strict”
  • JavaScript 本放在页面底部,加速烘托页面
  • JavaScript 脚本将脚本成组打包,减少恳求
  • 运用非堵塞办法下载 JavaScript 脚本
  • 尽量运用局部变量来保存大局变量
  • 尽量减少运用闭包
  • 运用 window 方针特色办法时,省掉 window
  • 尽量减少方针成员嵌套
  • 缓存 DOM 节点的拜访
  • 经过防止运用 eval()Function() 结构器
  • setTimeout()setInterval() 传递函数而不是字符串作为参数
  • 尽量运用直接量创立方针和数组
  • 最小化重绘 (repaint) 和回流 (reflow)

301. 下面的代码输出什么?

var a = function () { return 5 }
a.toString = function () { return 3 }
console.log(a + 7);

参考答案:

10

由于会主动调用 a 函数的 toString 办法。

注: 至此,JavaScript 内容就收拾完了,现在正在收拾关于网络方面的,我们能够等待一下。欢我们迎重视我哈,点击链接即可重视 法医,我们仔细看哦,奥利给!