JavaScript 常见面试题分析(二)
![](https://img.haomeiwen.com/i1662958/e33c3d66bebb68fd.jpg)
01 说明 this 几种不同的使用场景
this 要在执行时才能确认值,定义时无法确认
![](https://img.haomeiwen.com/i1662958/943edebebfe31d23.png)
① 作为构造函数执行 (this 指向创建出来的实例对象)
function Foo(name) {
this.name = name
}
var f = new Foo('年糕')
![](https://img.haomeiwen.com/i1662958/300b38f1eb38d07b.png)
② 作为对象属性执行 (this 指向调用该方法的对象)
var obj = {
name: 'Niangao',
printName: function() {
console.log(this.name)
}
}
obj.printName()
![](https://img.haomeiwen.com/i1662958/24128769c4791adf.png)
③ 作为普通函数执行 (this 指向 window)
function fn() {
console.log(this)
}
fn()
![](https://img.haomeiwen.com/i1662958/f3705d8e1da20947.png)
④ call()
方法 apply()
方法 bind()
方法 (this 指向第一个参数)
function fn1(name, age) {
console.log(name)
console.log(this)
}
fn1.call({x:100}, 'niangao', 17)
function fn2(name, age) {
console.log(name)
console.log(this)
}
fn2.apply({x:100}, ['niangao', 17])
var fn3 = function(name){
console.log(name)
console.log(this)
}.bind({y:200})
fn3('niangao')
![](https://img.haomeiwen.com/i1662958/68db9a9bd6686c68.png)
02 实际开发中闭包的应用
闭包实际应用中主要用于封装变量,收敛权限,下面是一个验证是否为第一次登陆的例子
function ifFirstLoad() {
var _list = [];
return function (id) {
if(_list.indexOf(id) >= 0) {
return false;
}else {
_list.push(id);
return true;
}
}
}
![](https://img.haomeiwen.com/i1662958/adaa1455b49d6917.png)
闭包的使用场景主要有两个:① 函数作为返回值;② 函数作为参数传递
function F1() {
var a = 100;
// 函数作为返回值
return function(){
console.log(a)
}
}
var f1 = F1();
function F2(fn) {
var a = 200;
// 函数作为参数传递
fn()
}
F2(f1)
03 创建 10 个 <a> 标签,点击的时候弹出对应的序号
for(var i = 0; i < 10; i++){
(function(i){
var div = document.createElement('div');
div.innerHTML = i + '<br>';
div.addEventListener('click', function(e){
e.preventDefault();
console.log(i);
})
document.body.appendChild(div)
})(i)
}
![](https://img.haomeiwen.com/i1662958/dfc1a1ebb474c000.png)
04 如何理解作用域
① 没有块级作用域,只有函数和全局作用域
② 自由变量
③ 作用域链,即自由变量的查找
// 无块级作用域
if(true){
var name = "niangao"
}
console.log(name) // niangao
// 函数和全局作用域
var a = 100;
function fn() {
var a = 200;
console.log('fn', a);
}
console.log('global', a) // global 100
fn() // fn 200
a 和 b 是自由变量——当前作用域没有定义的变量,即“自由变量”
![](https://img.haomeiwen.com/i1662958/2e2eef734d2e882d.png)
上面这个例子中,console.log(a);
并没有在当前作用域寻找到自由变量 a
,于是不断的往父级作用域寻找自由变量 a
,直到全局作用域,而能够沿着作用域一级级向上寻找的机制就称为“作用域链”
需要注意的是,一个函数的父级作用域是它定义时的作用域,而不是它执行时的作用域
![](https://img.haomeiwen.com/i1662958/68a066983241eff6.png)
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
请求,动态 <img>
加载),事件绑定
Ajax 请求代码示例
<script src="./jquery.js"></script>
<script type="text/javascript">
console.log('start');
$.get('./data.json', function(data) {
console.log(data);
})
console.log('end');
</script>
![](https://img.haomeiwen.com/i1662958/87404d2cc716ed1d.png)
<img>加载示例
console.log('start');
var img = document.createElement('img');
img.onload = function(){
console.log('loaded')
}
img.src = 'https://github.com/Niangao-Warren/JianShu/blob/master/Demo/Mouse_sliding_picture_showing_hidden/images/n1.jpg?raw=true';
console.log('end');
![](https://img.haomeiwen.com/i1662958/2c15c41e3b05b636.png)
事件绑定示例
![](https://img.haomeiwen.com/i1662958/f92aed947986a9b8.png)
![](https://img.haomeiwen.com/i1662958/c694d9d2d70b3092.png)
07 一道关于 SetTimeout 的题目
console.log(1);
setTimeout(function(){
console.log(2)
}, 0);
console.log(3);
setTimeout(function(){
console.log(4)
}, 1000);
console.log(5);
![](https://img.haomeiwen.com/i1662958/df0954caeb930047.png)
08 获取 2018-02-07 格式的日期
常用的日期 API 如下
Date.now() // 获取当前时间毫秒数
var 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;
}
![](https://img.haomeiwen.com/i1662958/7e7ef6668c52f1b9.png)
09 获取随机数,要求是长度一致的字符串格式
var random = Math.random();
var random = random + '0000000000' // 后面加上 10 个零
var random = random.slice(0, 10);
![](https://img.haomeiwen.com/i1662958/848c6cc57a7ba6a6.png)
10 写一个能遍历对象和数组的通用 forEach 函数
常用的数组 API 有
API | 作用 |
---|---|
forEach |
遍历所有元素 |
every |
判断所有元素是否都符合条件 |
some |
判断是否有至少一个元素符合条件 |
sort |
排序 |
map |
对元素重新组装,生成新数组 |
filter |
过滤符合条件的元素 |
forEach 遍历所有元素
item
对应的是元素的值,index
对应的是元素的位置
![](https://img.haomeiwen.com/i1662958/8c4f13a7550d84d6.png)
every 用来判断数组所有元素,都满足一个条件
![](https://img.haomeiwen.com/i1662958/7d3888f7c9b7d085.png)
some 用来判断数组所有元素,只要有一个满足条件即可
![](https://img.haomeiwen.com/i1662958/bd6f9b1cba2f7fce.png)
sort 排序
![](https://img.haomeiwen.com/i1662958/dd3c59fa6108f4b1.png)
map 对元素重新组装,生成新数组
![](https://img.haomeiwen.com/i1662958/f49e5c8f285c38f1.png)
filter 通过某一条件过滤数组
![](https://img.haomeiwen.com/i1662958/17e69c02e9ff9fb0.png)
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])
}
}
}
![](https://img.haomeiwen.com/i1662958/8f793804469c57ed.png)
End of File
行文过程中出现错误或不妥之处在所难免,希望大家能够给予指正,以免误导更多人,最后,如果你觉得我的文章写的还不错,希望能够点一下喜欢和关注,为了我能早日成为简书优秀作者献上一发助攻吧,谢谢!^ ^