题目三
- 说一下对变量提升的理解
- 变量定义(提升)
- 函数声明(提升)
- 说明
this
几种不同的使用场景 - 创建 10 个
<a>
标签, 点击的时候弹出不同的序号for(var i = 0; i < 10; i++) { (function(i){ var a = document.createElement('a') a.innerHTML =i + '<br>' a.addEventListener('click', function(e){ console.log(i) }) document.body.appendChild(a) })(i) }
- 如何理解作用域
- 自由变量
- 作用域链,查找自由变量
- 闭包的两个场景
- 实际开发中闭包的应用
// 封装变量, 收敛权限 function isFirstLoad() { var _list = [] return function (id) { if (_list.indexOf(id) >=0 ) { return false } else { _list.push(id) return true } } } var firstLoad = isFirstLoad() console.log(firstLoad(10)) // true console.log(firstLoad(10)) // false console.log(firstLoad(20)) // true
知识点
- 执行上下文
- 范围: 一段
<script>
或者一个函数 - 全局: 变量定义, 函数声明, 一段
<script>
- 函数: 变量定义, 函数声明,
this arguments
函数
<script>
console.log(a) // undefined 变量提升
var a = 100
fn('yym') // 'yym' 20
function fn(name) { // 函数声明 提升
age = 20
console.log(name,age)
var age
}
</script>
this
-
this
要在执行时才能确认值, 定义时无法确认- 作为构造函数执行
- 作为对象属性执行
- 作为普通函数执行
call apply bind
var a = {
name: 'yym',
fn: function () {
console.log(this.name)
}
}
// 不看下面, 上面不能确定this指啥
a.fn() // this === a
a.fn.call({name: 'B'}) // this === {name: B}
var fn1 = a.fn
fn1() // this === window
代码演示
function Foo(name) {
// this = {}
this.name = name
// return this
}
var f = new Foo('yym') // 构造函数的 this
var obj = {
name: 'A',
printName: function () {
console.log(this.name)
}
}
obj.printName() // 作为对象属性执行 this === Obj
function fn () {
console.log(this)
}
fn() // 作为普通函数执行 this === window
function fn1 (name) {
console.log(this)
}
fn1.call({x: 100}, 'yym') // call this === {x: 100} apply 第二个参数是数组
var fn2 = function (name) {
console.log(this)
}.bind({y: 150}) // .bind 是一个函数表达式
fn2('yym') // this === {y:150}
- 作用域
- JS没有块级作用域
- 只有函数和全局作用域
// 无块级作用域
if (true) {
var name = 'yym'
}
console.log(name) // 可以访问到 var name = 'yym'
// 函数和全局作用域
var a = 100
function fn() {
var a = 200
console.log('fn', a) // fn 200
}
console.log('global', a) // global 100
fn()
- 作用域链
var a = 100
function fn () {
var b = 200
// 当前作用域没有定义的变量, 即'自由变量'
console.log(a) // 在当前作用域找不到变量 a, 去父级作用域去找
console.log(b)
}
var a = 100
function F1 () {
var b = 200
function F2() {
// 当前作用域没有定义的变量, 即'自由变量'
console.log(a)
console.log(b)
console.log(c)
}
F2()
}
F1()
有 3个作用域: F2作用域, F1作用域, 全局作用域
a 在 F2 中没有, 去F1 作用域找, 没有, 继续去全局作用域找
b 在 F2 中没有, 在F1 作用域找到了
- 闭包
function F1() {
var a = 100
// 返回一个函数, (函数作为返回值)
return function () {
console.log(a) // 自由变量, 到父级作用域去找
}
}
var f1 = F1()
var a = 200
f1() // 100
- 闭包的使用场景
- 函数作为返回值
- 函数作为参数传递
// 函数作为参数传递
function F1() {
var a = 100
return function () {
console.log(a) // 自由变量, 到父级作用域去找
}
}
var f1 = F1()
function F2(fn) {
var a = 200
fn()
}
F2(f1) // 把f1 作为参数传进去 100
题目四
- 同步和异步的区别是什么? 分别举一个同步和异步的例子
- 同步会阻塞代码执行, 而异步不会
- alert是同步, setTimeout是异步
- 一个关于setTimeout的笔试题
console.log(1) setTimeout(() => { console.log(2) }, 0) console.log(3) setTimeout(() => { console.log(4) }, 1000) console.log(5) // 1 3 5 2 1s后打印 4
- 前端使用异步的场景有哪些
ajax 动态<img>加载
setTImeout setInterval
- 事件绑定
知识点
- 什么是异步 (对比同步)
console.log(100)
setTimeout(() => {
console.log(200)
}, 1000)
console.log(300)
如果是同步: 先打印100, 停顿1s后打印200, 然后打印300, 这肯定不是我们希望的,我们不希望它停顿
异步: 打印100, 打印300, 1s后打印200,不阻碍后面程序的加载
console.log(100)
alert(200) // 你什么时候点掉,什么时候执行后面的,会卡在那儿
console.log(300)
- 前端使用异步的场景
-
在可能发生等待的情况
-
等待过程中不能像alert一样阻塞程序进行
-
"等待的情况" 都需要异步
- 定时任务:
setTimeout setInterval
- 网络请求:
ajax
请求, 动态<img>
加载 - 事件绑定
// ajax请求, 异步 console.log('start') // 1.start $.get('url',function(data1) { // 异步 3.data1 console.log('data1') }) console.log('end') // 2.end // 事件绑定 异步 console.log('start') // 1.start $('#app').addEventListener('click', function () { alert('clicked') }) console.log('end') // 2.end
- 定时任务:
- 异步和单线程
- JavaScript是单线程语言,因此,在一个进程上,只能运行一个线程,而不能多个线程同时运行。也就是说JavaScript不允许多个线程共享内存空间。因此,如果有多个线程想同时运行,则需采取排队的方式,即只有当前一个线程执行完毕,后一个线程才开始执行。
- 任务队列
- 单线程就意味着,所有任务(线程)需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务不得不一直等待。
- 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,后一个任务才会执行;异步任务指的是不进入主线程、而进入任务队列的任务,只有当主线程上的所有同步任务执行完毕之后,主线程才会读取任务队列,开始执行异步任务。
console.log(100)
setTimeout(() => {
console.log(200)
})
console.log(300)
执行过程: 先打印100 , 遇到setTImeout异步会把里面的东西放到任务队列, 在打印 300,打印完成, 然后执行任务队列的工作
函数 setTimeout 接受两个参数:待加入队列的消息和一个延迟(可选,默认为0)。这个延迟代表了消息被实际加入到队列的最
小延迟时间。如果队列中没有其它消息,在这段延迟时间过去之后,消息会被马上处理。但是,如果有其它消息,
setTimeout 消息必须等待其它消息处理完。因此第二个参数仅仅表示最少延迟时间,而非确切的等待时间。
题目五
- 获取2019-02-10格式的日期
function formatDate(dt) { if (!dt) { dt = new Date() } var year = dt.getFullYear() var month = dt.getMonth() + 1 var date = dt.getDate() if (month < 10) { // 强制类型转换 month = '0' + month } if (date < 10) { // 强制类型转换 date = '0' + date } // 强制类型转换 return year + '-' + month + '-' + date } console.log(formatDate())
- 获取随机数,要求长度一致的字符串格式
var random =Math.random(); random = random+'0000000000' random = random.slice(0,10) console.log(random)
- 写一个能遍历对象和数组的通用
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]) } } } var arr = [1, 2, 3] forEach(arr, function (index, item) { console.log(index, item) }) var obj = {x: 100, y: 200} forEach(obj, function(key, value) { console.log(key, value) })
知识点
- 日期
Date.now() // 获取当前时间的毫秒数 1549788153194
var dt = new Date()
dt.getTime() // 获取毫秒数
dt.getFullYear() // 得到年
dt.getMonth() // 获取的是 0-11, 所以要 + 1
dt.getDate() // 获取日 0-31
dt.getHours() // 获取小时 0-23
dt.getMinutes() // 获取分钟 0-59
dt.getSeconds() // 获取秒 0-59
- Math
- 获取随机数
Math.random()
- 数组
API
-
forEach
遍历所有元素 -
every
判断所有元素是否都符合条件 -
some
判断是否至少一个元素符合条件 -
sort
排序 -
map
对元素重新组装,生成新数组 -
filter
过滤符合条件的元素
var arr = [1,2,3]
arr.forEach(function (item,index) {
// 遍历数组所有元素
console.log(index,item)
})
var result = arr.every(function (item, index) {
// 用来判断所有的数组元素,都满足一个条件
if( item < 4) {
return true
}
})
console.log(result) // true
var result = arr.some(function (item, index) {
// 用来判断所有的数组元素, 只要有一个满足条件即可
if( item < 2) {
return true
}
})
console.log(result) // true
var arr = [1,4,3,5,2]
var arr2 = arr.sort(function (a, b) {
// 从小到大排序
return a - b
})
console.log(arr2)
var arr = [1,2,3,4]
var arr2 = arr.map(function(item,index) {
// 将元素重新组装, 并返回
return item * 2
})
console.log(arr2)
var arr = [1,2,3]
var arr2 = arr.filter(function(item,index) {
// 通过某一条件过滤
if (item >= 2) {
return true
}
})
console.log(arr2) // [2, 3]
- 对象API
for in
var obj = {
x: 100,
y: 200,
z: 300
}
var key
for (key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key, obj[key])
}
}
网友评论