JavaScript 常见面试题分析(二)

JavaScript 常见面试题分析(二)_第1张图片
Unsplash
01 说明 this 几种不同的使用场景

this 要在执行时才能确认值,定义时无法确认

JavaScript 常见面试题分析(二)_第2张图片
运行结果

① 作为构造函数执行 (this 指向创建出来的实例对象)

function Foo(name) {
    this.name = name
}
let f = new Foo('Nian糕')
console.log(f.name) // Nian糕

② 作为对象属性执行 (this 指向调用该方法的对象)

let obj = {
    name: 'Nian糕',
    printName: function() {
        console.log(this.name)
    }
}
obj.printName() // Nian糕

③ 作为普通函数执行 (this 指向 window)

function fn() {
    console.log(this)
}
fn() // window

call() 方法 apply() 方法 bind() 方法 (this 指向第一个参数)

function fn1(name, age) {
    console.log(this)
}
fn1.call({x:100}, 'Nian糕', 17) // {x:100}

function fn2(name, age) {
    console.log(this)
}
fn2.apply({x:100}, ['niangao', 17]) // {x:100}

let fn3 = function(name){
    console.log(this)
}.bind({y:200})
fn3('niangao') // {y:200}
02 实际开发中闭包的应用

闭包实际应用中主要用于封装变量,收敛权限
闭包的使用场景主要有两个:① 函数作为返回值;② 函数作为参数传递;
闭包的影响:变量会常驻内存,得不到释放

// 验证是否为第一次登陆
function ifFirstLoad() {
    var _list = [];
    return function (id) {
        if(_list.indexOf(id) >= 0) {
            return false;
        }else {
            _list.push(id);
            return true;
        }
    }
}

// 一个简单的 cache 工具
function createCache() {
  // 闭包中的数据,被隐藏,不被外界访问
  const data = {}
  return {
    set: function (key, val) {
      data[key] = val
    },
    get: function (key) {
      return data[key]
    }
  }
}

// 异步请求 $.ajax(url, fn)
// React useEffect()
03 创建 10 个 标签,点击的时候弹出对应的序号
for(var i = 0; i < 10; i++){
    (function(i){
        let div = document.createElement('div');
        div.innerHTML = i + '
'; div.addEventListener('click', function(e){ e.preventDefault(); console.log(i); }) document.body.appendChild(div) })(i) }
04 如何理解作用域

① 全局作用域、函数作用域、块级作用域
② 自由变量,即当前作用域没有定义的变量
③ 作用域链,即自由变量的查找

// 块级作用域
if(true){
    let name = "niangao"
}
console.log(name) // 报错

// 函数和全局作用域
var a = 100;
function fn() {
    var a = 200;
    console.log('fn', a);
}
console.log('global', a) // global 100
fn() // fn 200

a 和 b 是自由变量——当前作用域没有定义的变量,即“自由变量”

运行结果

上面这个例子中,console.log(a); 并没有在当前作用域寻找到自由变量 a,于是不断的往父级作用域寻找自由变量 a,直到全局作用域,而能够沿着作用域一级级向上寻找的机制就称为“作用域链”

需要注意的是,一个函数的父级作用域是它定义时的作用域,而不是它执行时的作用域

JavaScript 常见面试题分析(二)_第4张图片
运行结果
05 同步和异步的区别是什么

同步会阻塞代码执行,而异步不会

//异步
console.log(100);
setTimeout(function(){
    console.log(200);
}, 1000)
console.log(300);

//同步
console.log(100);
alert(200);
console.log(300);
06 前端使用异步的场景有哪些

在可能发生等待的情况下,我们会需要异步,比如定时任务(setTimeout, setInterval),网络请求(Ajax 请求,动态 加载),事件绑定

Ajax 请求代码示例



JavaScript 常见面试题分析(二)_第5张图片
运行结果

加载示例

console.log('start');
var img = document.createElement('img');
img.onload = function(){
    console.log('loaded')
}
img.src = 'https://upload.jianshu.io/users/upload_avatars/1662958/91d53dd877a7?imageMogr2/auto-orient/strip|imageView2/1/w/80/h/80/format/webp';
console.log('end');
// start end loaded
07 一道关于 SetTimeout 的题目
console.log(1);
setTimeout(function(){
    console.log(2)
}, 0);
console.log(3);
setTimeout(function(){
    console.log(4)
}, 1000);
console.log(5);
// 1, 3, 5 -> 2 -> 4
08 获取 2018-02-07 格式的日期

常用的日期 API 如下

Date.now() // 获取当前时间毫秒数
let today = new Date()
today.getTime() // 获取毫秒数
today.getFullYear() // 年
today.getMonth() // 月(0-11)
toddy.getDate() // 日(0-31)
today.getHours() // 时(0-23)
today.getMinutes() // 分(0-59)
today.getSeconds() // 秒(0-59)
function formatDate(today) {
    if(!today) {
        today = new Date()
    }
    var year  = today.getFullYear(),
        month = today.getMonth() + 1,
        date  = today.getDate();
    if(month < 10) {
        month = '0' + month;
    }
    if(date < 10) {
        date = '0' + date;
    }
    return year + '-' + month + '-' + date;
}
09 写一个能遍历对象和数组的通用 forEach 函数
function forEach(obj, fn) {
    var key;
    if(obj instanceof Array) {
        obj.forEach(function(item, index) {
            fn(index, item)
        })
    }else {
        for(key in obj) {
            fn(key, obj[key])
        }
    }
}
JavaScript 常见面试题分析(二)_第6张图片
运行结果
End of File

行文过程中出现错误或不妥之处在所难免,希望大家能够给予指正,以免误导更多人,最后,如果你觉得我的文章写的还不错,希望能够点一下喜欢关注,为了我能早日成为优秀作者献上一发助攻吧,谢谢!^ ^

你可能感兴趣的:(JavaScript 常见面试题分析(二))