块级作用域
1. 块级作用域
//ES5
if (true) {
var x = 2;
console.log(x); //2
}
console.log(x); //2 if代码块中定义的变量在外部依然能够访问
//使用闭包解决
function foo() {
var x = 1;
if (x === 1) {
(function() {
var x = 2;
//some code...
})();
}
if (true) {
var x = 2;
console.log(x); //2
}
console.log(x);
console.log(x); //1
}
foo();
2. 变量提升
console.log(x);
var x=1;
//实际运行过程
var x;
console.log(x);
x=1;
3. let 关键字
- 同一个块级作用域中不能使用 let 关键字重复声明同一个变量
- 解决 es5 中变量提升的问题
4. const 关键字
- 声明常量
- 适用于 node 中模块引入
const 什么的变量不可修改,但是定义的对象却是可以修改的
//const内壁是依靠指针来判断一个对象是否被修改的
const obj = {};
obj.name = "eastboat";
b.age = 118;
数组
ES6 新增如下原型方法:
- cpoyWithin()
- find()
//返回相应元素的值
let arr = [1, 2, -3, 4];
var index = arr.find(function(n) {
return n < 0;
});
console.log(index); //-3
- findnedx()
//返回相应元素的位置
let arr = [1, 2, -3, 4];
var index = arr.findIndex(function(n) {
return n < 0;
});
console.log(index); // 2
- from()
//伪数组转化为真正数组
var arr = Array.prototype.slice.call(arrLike);
//from方法
var arr = Array.from(arrLike);
- fill()
//es5
var arr = Array.apply(null, new Array(5))
// [undefined,undefined,undefined,undefined,undefined]
.map(function() {
return 0;
});
// [0,0,0,0,0]
//es6
var arr = new Array(5).fill(0); // [0,0,0,0,0]
数组遍历
- entries()
- keys()
- values()
函数
参数默认值
function greed(x = "hello", y = "Node") {
console.log(x, y);
let x = "123"; // 如果参数使用了默认值就不能在方法中内再使用let关键字声明同名变量
var y = "456"; //正常
}
greed();
Spread 运算符
function foo(x, y, z) {
return x + y + z;
}
var args = [1, 2, 3];
foo(...args);
箭头函数
var func = a => a;
//等价
var func = function(a) {
return a;
};
this 指向问题
var person={
name:"Eastboat",
sayName:function(){
// var self=this;
var func=function(){
return this.name
}
return func();
}
}
person.sayName() // undefined
‘
/*
常用解决方案 :
1.var self=this;
2.箭头函数改写
*/
匿名函数中的 this,默认指向全局 windowd 对象,使用箭头函数也可以改变
var obj = {};
obj.foo = function() {
console.log(this)(
// Object {foo:[Function]}
() => {
console.log(this); //{foo:[Function]}
}
)();
};
setTimeout 中匿名函数的 this 指向,在浏览器中是 window 对象,在 Node 中是一个 Timeout 对象
原型扩展以及继承的时候,注意箭头函数 this 指向的陷阱
Set 和 Map
Set
类似数组的数据结构,但是不能包含重复数据
var set = new Set([1, 1, 1, 2]);
console.log(set); //[1,2]
set.add(3);
set.delete(1);
set.has(2); //true
set.clear(); //清除所有的元素
//Set的遍历
let set = new Set([1, 2, 3]);
for (let i of set.keys()) {
console.log(i); //[Set Iterator] { 1, 2, 3 }
}
for (let i of set.values()) {
console.log(i); // [Set Iterator] { 1, 2, 3 }
}
for (let i of set.entries()) {
console.log(i); //[Set Iterator] { 1, 2, 3 }
}
WeakSet
- 与 Set 的区别是,**WeakSet 的成员只能是对象
- weak 一词是弱引用的意思,这是一个垃圾回收的概念,表示 WeakSet 中存储的是对象的弱引用,一旦垃圾回收器扫描,发现只有弱引用的对象就会子回收阶段将其内存回收,也就表示 WeakSet 中存储的对象如果没有被其他对象所引用,其内存空间就会被回收,开发者一般无法控制 GC 的运行,因此 WeakSet 的值是无法预测的,它不支持遍历,也不能使用 size 属性来得到其大小
let weakSet = new WeakSet();
weakSet.add({ a: 1, b: 2 });
console.log(weakSet); //WeakSet { [items unknown] }
运用场景:对垃圾回收有利,假设在一个局部作用域中产生了一个中间值的对象,如果作用域外没有引用这个对象,那么就可以使用 WeakSet 存储它,在它离开作用域之后,该对象就会在下一轮垃圾回收时被销毁
Map
表示由键值对组成的有序集合, 有序表现在 Map 的遍历顺序就是插入顺序,ES5 中也有类似的结构,但是键值对的键值只能是 String 类型,ES6 新增的 Map 支持多种类型作为键值,包括对象和布尔值
let obj = { name: "Eastboat" };
let map = new Map([["a", 1], ["b", 2], [obj, 3]]);
console.log(obj); //{ name: 'Eastboat' }
console.log(map); //Map { 'a' => 1, 'b' => 2, { name: 'Eastboat' } => 3 }
console.log(map.size); //3
console.log(map.has("a")); //true
console.log(map.get("a")); //1
map.set("name", "cccc");
console.log(map);
/*
Map {
'a' => 1,
'b' => 2,
{ name: 'Eastboat' } => 3,
'name' => 'cccc' }
*/
for (let i of map.keys()) {
console.log(i);
/*
a
b
{ name: 'Eastboat' }
name
*/
}
for (let i of map.values()) {
console.log(i); // 1,2,3,ccc
}
for (let i of map.entries()) {
console.log(i);
/*
[ 'a', 1 ]
[ 'b', 2 ]
[ { name: 'Eastboat' }, 3 ]
[ 'name', 'cccc' ]
*/
}
WeakMap
WeakMap 和 WeakSet 类似,但是作为 key 的必须是一个对象,弱引用的特性和 WeakSet 相同
Iterator
如何遍历数据结构,一种遍历的方法就是 Iterator,js 中的 Iterator 是通过 Symbol.iterator 属性实现的,如果一个对象设置了 Symbol.iterator 属性,就表示这个对象是能被遍历的,我们可以用 next 方法来遍历它
let Iter = {
[Symbol.iterator]: function() {
let i = 0;
return {
next: function() {
return ++i;
}
};
}
};
let instance = new Iter[Symbol.iterator]();
console.log(instance); //{ next: [Function: next] }
let a = instance.next();
let b = instance.next();
let c = instance.next();
let d = instance.next();
console.log(a, b, c, d); // 1,2,3,4
ES6 中,所有内部实现了 Symbol.iterator 接口的对象都可以使用 for..of 循环进行遍历
function myIter(array) {
this.array = array;
}
myIter.prototype[Symbol.iterator] = function() {
let index = 0;
return {
next: () => {
if (index < this.array.length) {
return {
value: this.array[index++],
done: false
};
} else {
return {
value: undefined,
done: true
};
}
}
};
};
var instance2 = new myIter([1, 2, 3]);
for (var i of instance2) {
console.log(i); //1,2,3
}
对象
Object.assign()
将一个对象的属性复制到另一个对象上
//浅拷贝
let obj1 = {
a: {
b: 1
}
};
let obj2 = Object.assign({}, obj1);
console.log(obj2); //{ a: { b: 1 } }
obj2.a.b = 22222;
console.log(obj1, obj2); //{ a: { b: 22222 } } { a: { b: 22222 } }
Object.setPrototypeOf()
用来设置一个对象的 prototype 对象,返回参数对象本身,作用和直接设置
__proto__
属性相同
Object.getPrototypeOf()
用来获取一个对象的原型对象,和上述方法配套
let Person = function(name, age) {
this.age = age;
this.name = name;
this.greed = function() {
console.log(`Hi,I am ${this.name}`);
};
};
let Student = function() {};
let stuPerson = new Student();
//设置原型对象 prototype
Object.setPrototypeOf(stuPerson, Person);
console.log(stuPerson.__proto__); //[Function: Person]
//读取原型对象
console.log(Object.getPrototypeOf(stuPerson)); //[Function: Person]
网友评论