JS 面试题及相关知识点合集

2019-01-08  本文已影响0人  无故下架内容so账号已弃用

1. JS 中使用 typeof 能得到哪些类型?
undefined string boolean object number function

console.log(typeof undefined);
// "undefined"
console.log(typeof 'sfsgsdf');
// string
console.log(typeof 123);
// number
console.log(typeof true);
// boolean
console.log(typeof {a:1});
// object
console.log(typeof ['ddf']);
// object
console.log(typeof null);
// object
console.log(typeof function (){});
// function
console.log(typeof console.log);
// function

2. 何时使用 === 何时使用 ==
if ( obj.a == null) { }
这里的 obj.a == null 相当于 obj.a === null || obj.a == undefined,
除了上面这种情况都采用 ===。

解释:
==:等同,比较运算符,两边值类型不同的时候,先进行类型转换,再比较
===:恒等,严格比较运算符,不做类型转换,类型不同就是不等
补充:Object.is()是ES6新增的用来比较两个值是否严格相等的方法,与===的行为基本一致,

console.log(Object.is(123,'123')); // false
console.log(Object.is(345,345)); // true
console.log(NaN === NaN); // false
console.log(Object.is(NaN,NaN)); // true
console.log(+0=== -0); // true
console.log(Object.is(+0,-0)); // false

3. JS 中有哪些内置函数
Array Object String Boolean Function Number RegExp Error

补充:Math 是个内置对象

4. JS 变量按照存储方式区分为哪些类型,并描述其特点
(1) 值类型:
值类型的变量是存放在栈区的,栈区中包括了变量的标识符以及变量所对应的值

var a = 12;
var b = a;
console.log(a); // 12
console.log(b); // 12
b = 20;
console.log(a); // 12
console.log(b); // 20

(2) 引用类型:
引用类型的变量也是存放在栈区的,不同的是,引用类型在栈区中存放的是变量标识符以及变量所对应值的引用地址,而变量所对应的值被存放在堆区中。

所以下列代码给 b 赋值的时候是把 a 的引用地址赋给了 b,这就是修改 b.age后,a.age 也发生了变化的原因

var a = { age: 12 };
var b = a;
console.log(a.age); // 12
console.log(b.age); // 12
b.age = 20;
console.log(a.age); // 20
console.log(b.age); // 20

5. 理解 JSON
JSON 是 JS 的一个对象,有以下方法:
(1) 将 json 对象转换成字符串
JSON.stringify({a:"aaa","b":1214});
// '{"a":"aaa","b":1214}'
(2) 将字符串转换成 json 对象
JSON.parse('{"a":"aaa","b":1214}');
JSON.parse("{'a':'aaa','b':1214}"); // 报错

注意:JSON 对象应该是双引号

6. 如何准确判断一个变量是数组类型

方法1:利用 instanceof

var obj = {a:0,b:1};
var arr = [1,2,3,4,'fff'];
console.log(obj instanceof Array); // false
console.log(arr instanceof Array); // true

实际上这个方法不能正确判断变量的类型

方法二:利用 Object.prototype.toString 方法

<script>
var obj = {a:0,b:1};
var arr = [1,2,3,4,'fff'];
// Object.prototype.toString.call(obj) // [object Object]
// Object.prototype.toString.call(arr) // [object Array]
function isArrayFn (o){
    var str = Object.prototype.toString.call(o);
    if(str === '[object Array]') {
      return true;
    }else {
        return false;
    }
}
console.log(isArrayFn(obj)); // false
console.log(isArrayFn(arr)); // true
</script>

这是常用的方法:Object.prototype.toString, 还可以用来区别 Function Object Number等

console.log(Object.prototype.toString.call("dfgs分dfgdf"));//[object String]
console.log(Object.prototype.toString.call(123));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "gdsfgs"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([1,2,3]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]

方法三: ES6 中的 Array.isArray()
用 ES6 中的 Array.isArray() 判断非常简单,

<script>
  var obj = {a:0,b:1};
  var arr = [1,2,3,4,'fff'];
  console.log(Array.isArray(obj)); // false
  console.log(Array.isArray(arr)); // true
</script>

7. 描述 new 一个对象的过程

8. Jquery(或其他框架) 源码中如何使用原型链

<div id="box">内容</div>
<script>
    function Elem (id) {
        this.elem = document.getElementById(id);
    }

    Elem.prototype.html = function (val){
        var elem = this.elem;
        if(val){
            // 设置
            elem.innerHTML = val;
            return this; // 链式调用
        }else {
            // 获取
            return elem.innerHTML
        }
    }

    Elem.prototype.on = function (type, Fn){
        var elem = this.elem;
        elem.addEventListener(type,Fn,false);
    }

    // var oBox = new Elem('box');
    // oBox.html('点击我').on('click', function (){ alert('点击了') });
    function Jquery(id) {
        return new Elem(id);
    }
    window.$ = window.jQuery = Jquery;

    $('box').html('点击我').on('click', function (){ alert('点击了') });
</script>

关于更多原型链的知识点,请移步:面试知识点之原型链

8. 说一下对变量提升的理解
JS 的预解析:
在当前作用域下,JS 代码在正式开始执行之前,进行的一些解析工作: 会把带有 var 和 function 关键字的事先声明,并在内存中安排好,这个过程也可以理解为变量提升,然后再从上到下执行 JS 语句,例如:

  1. 把 var 声明的 num 变量的初始化提升到该作用域的最前面:
console.log(num);
var num = 123;
// 结果:undefined
// 代码实际运行过程
var num; // var num = undefined;
console.log(num);
num = 123;
  1. 把 var 声明的 fn 变量的初始化提升到该作用域的最前面:
console.log(fn);
var fn = function (){};
// 结果:undefined
// 代码实际运行过程
var fn; // var fn= undefined;
console.log(fn);
fn= function (){};
  1. 把 function 声明的整个函数提升到该作用域的最前面:
console.log(f);
function f(){}
// 结果:ƒ f(){}
// 代码实际运行过程
function f(){}
console.log(f);
  1. 再看看下面的情况:
console.log(a);
var a = 1;
function a(){};
console.log(a);
// 结果:
// ƒ a(){}
// 1
// 代码实际运行过程:
var a; // var a= undefined;
function a(){};
console.log(a);
a = 1;
console.log(a);

9. 说明 this 几种不同的使用场景

10. 创建 10 个 <a> 标签,点击的时候弹出来对应的序号
考点:作用域

<script>
    var oDiv = document.createElement('div'),
        oBody = document.body;
    for (var i = 0; i < 10; i++) {
        (function (i){
            var link = document.createElement('a');
            link.innerHTML = '第' + (i +1) + '个A '
            link.addEventListener('click',function (ev){
                var ev = ev || window.event;
                ev.preventDefault();
                alert(i+1);
            },false);
            oDiv.appendChild(link);
        }(i))
    }
    oBody.appendChild(oDiv);
</script>

ES6 用 let 的块级作用域实现方法 :

<script>
    var oDiv = document.createElement('div'),
        oBody = document.body;
    for (let i = 0; i < 10; i++) {
        var link = document.createElement('a');
        link.innerHTML = '第' + (i +1) + '个A '
        link.addEventListener('click',function (ev){
            var ev = ev || window.event;
            ev.preventDefault();
            alert(i+1);
        },false);
        oDiv.appendChild(link);
    }
    oBody.appendChild(oDiv);
</script>

11. 如何理解作用域
执行环境:全局执行环境局部执行环境
全局执行环境是最外围的执行环境,全局执行环境被认为是 window 对象,它所对应的就是全局作用域
即在全局执行环境下定义的变量,叫全局变量,对任何内部函数来说,都是可以访问的,
局部执行环境一般指函数内部或者固定的代码片段内(ES6中引进块级作用域的概念),函数内定义的就是局部变量,只有在该函数内部及内部所有的函数才可以访问到这个变量,
特别需要注意的是: 非严格模式下,在任何地方不声明直接使用变量,变量会成为全局变量,在严格模式下,不允许变量不声明直接使用
比如:

var num = 0;
function fn(){
  num1 = 123;
  var num2 = 456;
  var num3 = 789;
  console.log(num3);
}
fn(); // 789
console.log(num); // 结果: 0,num 是全局变量
console.log(num1); // 结果: 123, num1 是全局变量
console.log(num2); // 报错,num2 是 fn 函数的局部变量,函数外部访问不到

12. 实际开发中闭包的应用

13. 同步和异步的区别

14. 前端使用异步的场景有哪些

15. 获取 xxxx-xx-xx 格式的日期

<script>
// 获取 xxxx-xx-xx 格式的日期
function formatDate (date) {
    if ( !date ) {
        date = new Date()
    }
    var year = date.getFullYear()
    var month = date.getMonth() + 1
    var day = date.getDate()

    month = addZero(month)
    day = addZero(day)

    return year + '-' + month + '-' + day
}

function addZero (num) {
    return num < 10 ? '0' + num : num
}

var d = formatDate(new Date())
console.log(d)
</script>

16. 获取随机数,要求是长度一致的字符串格式

<script>
    function getRandom() {
        var random = Math.random() + '0000000000'
        return random.slice(0,11)
    }
    getRandom()
</script>

17. 写一个能遍历数组和对象的 forEach 函数

<script>
    var a = [1,23,26,5,2]
    var b = {num:1,str:'gggg'}
    
    function forEach (obj, fn) {
        var getObjectString = Object.prototype.toString;
        if(getObjectString.call(obj) === '[object Array]') {
            // 如果 obj 是数组
            obj.forEach(function (item,index) {
                fn(index,item)
            })
        }else if (getObjectString.call(obj) === '[object Object]'){
            // 如果 obj 是{}
            for (var index in obj) {
                fn(index,obj[index])
            }
        }
        return;
    }

    forEach(a,function (key, value){
        console.log(key,value)
    })
// 结果: 
// 0 1
// 1 23
// 2 26
// 3 5
// 4 2
    forEach(b,function (key, value){
        console.log(key,value)
    })
// 结果:
// num 1
// str gggg
</script>

18. DOM 是那种基本的数据结构

19. DOM 操作的常用 API 有哪些

<div id="box" data-id="222"></div>
<div class="box"></div>
<div class="box"></div>
<span></span>
<span></span>
<script>
    console.log(document.getElementById('box')) // 元素 <div id="box"></div>
    console.log(document.getElementsByTagName('span'))  // 集合
    console.log(document.getElementsByClassName('.box')) // 集合
    console.log(document.querySelector('#box')) //  元素
    console.log(document.querySelectorAll('.box')) //  集合

    // property
    var obj = {a:'dsfgsdg'}
    console.log(obj.a); // dsfgsdg
    // 或者
    console.log(document.getElementById('box').nodeType) // 1 nodeType:1 表示节点类型是元素

    // Attribute
    console.log(document.getElementById('box').getAttribute('data-id')) // 222
    document.getElementById('box').setAttribute('data-type','dom') // 结果: <div id="box" data-id="222" data-type="dom"></div>
</script>
<div id="box-container">
    <div id="box"></div>
</div>
<script>
    console.log(document.getElementById('box').parentNode)
    // <div id="box-container"><div id="box"></div></div> 获取到了父节点

    console.log(document.getElementById('box-container').childNodes[0])
    // #text 获取到了文本节点
    console.log(document.getElementById('box-container').childNodes[1])
    // <div id="box"></div> 获取到了文本节点
</script>
// 新增节点
<div id="box"></div>
<script>
    //创建元素 span 
    var oSpan = document.createElement('span')
    oSpan.innerHTML = 'span'
    document.getElementById('box').appendChild(oSpan)
</script>
// 删除节点
<div id="box">
    <div class="box-child"></div>
</div>
<script>
    var boxChild = document.querySelector('.box-child')
    // 删除子节点 .box-child
    document.getElementById('box').removeChild(boxChild)
</script>

20. DOM 节点的Attribute 和 property 有何区别

21. 编写一个通用的事件监听函数

<div class="box" data-name="父元素 box">
    <p data-name="张三">猜猜我是谁?</p>
    <p data-name="李四">猜猜我是谁?</p>
    <p data-name="王五">猜猜我是谁?</p>
    <p data-name="老六">猜猜我是谁?</p>
    <div data-name="假七">猜猜我是谁?</div>
</div>
<script>
    function bindEvent (el, type, child, fn) {
        if (fn == null) {
            // fn == null 等价于 fn === null || fn === undefined
            // 如果没有 child 的参数
            fn = child
            child = null
        }

        el.addEventListener(type, function (e) {
            if (child == null) {
                // fn(e) 课程是这个写法,但是我觉得这样写,this 指向了 window,是不正确的,所以改写成了下面的
                fn.call(el,e)
            } else {
                var ev = ev || window.event,
                    target = ev.target
                ev.preventDefault() // 阻止默认行为
                if(target.nodeName === child || target.nodeName.toLowerCase() === child) {
                    fn.call(target, e)
                }
            }
        }, false)
    }


    var box = document.querySelector(".box")
    bindEvent(box, 'click', function (e){
        alert(this.getAttribute('data-name'))
    })

    bindEvent(box, 'click', 'p', function (e){
        alert(this.getAttribute('data-name'))
    })
</script>

22. 手动编写一个 ajax,不依赖第三方库

api.json

{
    "name":"json"
}
<script>
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'http://192.168.0.14:8080/api.json', false)
    xhr.setRequestHeader('Content-Type','application/json')
    xhr.onreadystatechange = function (){
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                console.log(xhr.responseText)
            }
        }
    }
    xhr.send()
</script>

移步查看更多 ajax 的具体知识点 面试知识点之 ajax 与跨域

23. window.onload 和 DOMContentLoaded
window.onload: 页面的全部资源加载完才会执行,包括图片、视频等
DOMContentLoaded: DOM 结构加载完就可以执行,此时图片、视频还没加载完

window.addEventListener('load', function (){
    console.log('load')
})
window.addEventListener('DOMContentLoaded', function (){
    console.log('DOMContentLoaded')
})
// 结果:
// DOMContentLoaded
// load

jquery zepto 等一般使用 DOMContentLoaded

以上为学习笔记,参考资料来源:慕课网的课程

上一篇下一篇

猜你喜欢

热点阅读