7. this指向
确认this指向是在执行代码的时候,而不是定义代码的时候。因为this是执行上下文的一部分。
Example1:
var a = { name: 'A', fn: function () { console.log(this.name) } } a.fn() // this === a a.fn.call({name: 'B'}) // this === {name: 'B'} var fn1 = a.fn fn1() // this === window
解析:
this执行会有不同,主要集中在这几个场景中
- 作为构造函数执行,构造函数中
- 作为对象属性执行,上述代码中a.fn()
- 作为普通函数执行,上述代码中fn1()
- 用于call apply bind,上述代码中a.fn.call({name: 'B'})
Example2:
var x = 0;
function test() {
console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply({x: 2}) // 2 //apply()的参数为空时,默认调用全局对象。
obj.m.apply() // 0 //apply()的参数为空时,默认调用全局对象。
obj.m.apply(obj) // 1 //apply()的参数为空时,默认调用全局对象。
8. 同步和异步
Example1: (异步)
console.log(100)
setTimeout(function(){
console.log(200)
},100)
console.log(300)
解析:
打印顺序:100,300, 200.
原因:因为js是单线程,会把3个打印任务存入队列之中,会异步继续往下执行。所以是先打印100, 300,最后第二个console是在100ms以后打印的
Example2: (单线程)
var test = true
setTimeout(function(){
test = false
})
while(test){
console.log(100)
}
解析:
while循环的判断条件是,test为true时执行,每执行完一遍时,继续从头重新执行。因为js是单线程,而while的这个特性会将js的单线程占满,不会有时间(线程)去跑setTimeout了。所以,答案是死循环。
9. ES6 / ES7新标准的考察
class声明构造函数:取代之前的构造函数,从语法更加符合面向对象的写法。
基本格式:
class Name() {
constructor(a,b) {
...
}
say() {
...
}
}
const a = new Name(1,2)
a.say();
//es6的class实现继承
class Animal{
constructor(name) {
this.name = name
// console.log(this.name, '--this.name--')
}
eat() {
console.log(`${this.name}` + '吃东西')
}
}
class Dog extends Animal {
constructor(name){
super(name)
this.name = name
}
say() {
console.log(`${this.name} say`)
}
}
var hashiqi = new Dog('哈士奇')
hashiqi.eat()
hashiqi.say()
注意:
1. 使用extends即可实现继承,更符合面向对象的语言的写法
2. 子类的constructor一定要使用super,以继承父类的constructor.
10. es6新增的数据类型:set 和 map
set和map是对当前数组和对象的扩展。
set和map的重要特性:
1. set不允许数组存在重复的元素。
Example:
const set = new Set();
[1,2,3,3,1,2,3].forEach(item => set.add(item))
console.log(set, '--set--')//Set(3) {1, 2, 3}
Set 实例的属性和方法有:
- size:获取元素数量。
- add(value):添加元素,返回 Set 实例本身。
- delete(value):删除元素,返回一个布尔值,表示删除是否成功。
- has(value):返回一个布尔值,表示该值是否是 Set 实例的元素。
- clear():清除所有元素,没有返回值。
Set 实例的遍历,可使用如下方法
- keys():返回键名的遍历器。
- values():返回键值的遍历器。不过由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys()和values()返回结果一致。
- entries():返回键值对的遍历器。
- forEach():使用回调函数遍历每个成员
2. map允许key值是任何数据类型,普通对象只能是字符串或数组
Example:
const map = new Map();
const obj = {p: 'Hello World'};
map.set(obj, 'OK') //Map中可以将任何数据类型存为key值(包括对象)
console.log(map.get(obj)) // "OK"
console.log(map.has(obj)) // true
console.log(map.delete(obj)) // true
console.log(map.has(obj)) // false
Map 实例的属性和方法如下:
- size:获取成员的数量
- set:设置成员 key 和 value
- get:获取成员属性值
- has:判断成员是否存在
- delete:删除成员
- clear:清空所有
Map 实例的遍历方法有:
- keys():返回键名的遍历器。
- values():返回键值的遍历器。
- entries():返回所有成员的遍历器。
- forEach():遍历 Map 的所有成员。
10. iterator
Iterator接口(iterator对象,迭代器对象)
对于可迭代的数据解构,ES6在内部部署了一个[Symbol.iterator]属性,它是一个函数,执行后会返回iterator对象(也叫迭代器对象,也叫iterator接口),拥有[Symbol.iterator]属性的对象即被视为可迭代的,比如一个空数组。
iterator是一个对象,具有一个next方法可以调用。
Example:
var arr = [1,2,3]
let iterator = arr[Symbol.iterator]() //需要使用键值对的形式访问Symbol.iterator
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
解析:
next方法返回又会返回一个对象,有value和done两个属性,value即每次迭代之后返回的值,而done表示是否还需要再次循环,可以看到当value为undefined时,done为true表示循环终止。
梳理一下:
- 可迭代的数据结构会有一个[Symbol.iterator]方法
- [Symbol.iterator]执行后返回一个iterator对象
- iterator对象有一个next方法
- next方法执行后返回一个有value,done属性的对象