Objects中的属性:
- 1: Object.keys 和 Object.getOwnPropertyNames: 检索对象中所有的属性名,前一个方法返回所有可枚举的属性名,后一个方法不考虑属性的可枚举性一律返回, 但都不支持Symbol属性,ES6中增加 Object.getOwnPropertySymbols()方法来检索对象中的Symbol属性
- 2:
//obj instanceof Array == Array[Symbol.hasInstance](obj)
function specailNumber(){}
Object.defineProperty(specailNumber,Symbol.hasInstance,{value:(v)=>(v instanceof Number) && (v >= 1 && v <= 100)})
var two = new Number(2)
zero = new Number(0)
print(two instanceof specailNumber)
print(zero instanceof specailNumber)
-------------------------------------------------------------------
let collection = {
0:"hello",
1:"world",
length:2,
[Symbol.isConcatSpreadable]:true
};
let message = ["HI"].concat(collection);
print(message) //[ 'HI', 'hello', 'world' ]
0 ES5 有5种类型, ES6有6种类型
- 1: ES5: 字符串型,数字型,布尔型,null,undefined
- 2 : ES6 + Symbol ,Symbol是原始值,因此调用new Symbol() 会报错. 但是可以
typeof symbol
- 3: Symbol的描述被存储在内部的[[Description]]属性中,只有当调用Symbol的toString()方法时才可以读这个属性
- 4: 所有使用可计算属性名的地方,都可以使用Symbol.Object.defineProperty()方法和Object.defineProperties()方法
- 5: Symbol.for("uid"), 首先在全局Symbol注册表中搜索键为"uid"的Symbol是否存在,存在返回,不存在,创建新的Symbol并返回
let firstname = Symbol("firstname");
//可计算
let person = {
[firstname]:"Nichols"
};
//将属性设置为只读
Object.defineProperty(person,firstname,{writable:false});
let lastname = Symbol("last name");
Object.defineProperties(person,{
[lastname]:{
value:"Zakes",
writable:false
}
});
print(person.firstname,person.lastname);
1 箭头函数
- 1: 没有this,super,arguments和new.target绑定,箭头函数中的 this,super,arguments和new.target这些值由外围最近一层非箭头函数决定,
- 2: 不能通过new关键字调用, 箭头函数没有[[]Construct]方法,所以不能作为构造函数,如果用了new就会抛出错误.
- 3: 没有原型,由于不能通过new构造,因而没有构造原型的需求,所以箭头函数不存在prototype这个属性
- 4: 不可以改变this的绑定,函数内部的this值不可以改变,在函数的生命周期内始终保持一致.
- 5: 不支持 arguments对象,箭头函数没有arguments绑定,所以你必须通过明明函数和不定参数这两种形式访问函数的参数.
- 6: 不支持重复的命名参数 无论严格参数还是非严格模式下,箭头函数都不支持重复的命名参数
- 7: 箭头函数同样也有一个name属性,这与其他函数相同.
- 8: 箭头函数的设计初衷是: 即用即弃, 箭头函数内的this也不能通过call apply bind来改变.
但是可以在箭头函数上调用call apply bind方法,与其他函数不同,箭头函数的this值不会受这些方法的影响
var sum = (num1,num2) => num1+num2;
print(sum.call(null,1,2))
print(sum.apply(null,[1,2]))
var boundSum = sum.bind(null,1,2)
print(boundSum())
2 ES6中尾递归优化: 满足以下条件,尾调用不再创建新的栈帧,而是清除并重用当前栈帧
- 1: 尾调用不访问当前栈帧的变量(也就是说函数不是一个闭包)
- 2: 在函数内部,尾调用是最后一条语句
- 3: 尾调用的结果作为函数值返回
3: js中的对象 普通对象
特异对象
标准对象
内建对象
- 1: 普通对象(ordinary): 具有js对象所有的默认内部行为
- 2: 特异对象(exotic) 具有某些与默认行为不符的内部行为
- 3: 标准对象: ES6规范中定义的对象.Array Date等
- 4: 内建对象: 脚本开始执行时存在于js执行环境中的对象,所有标准对象都是内建对象.
4: Object.assign and 自有属性的枚举顺序
- 1: 所有数字按升序排序
- 2: 所有字符串键按照他们被加入对象的顺序排序
- 3: 所有symbol键按照他们被加入对象的顺序排序
var obj = {
a:1,
0:1,
c:1,
2:1,
b:1,
1:1
};
obj.d = 1;
print(Object.getOwnPropertyNames(obj).join("")) //012acbd
5: 改变对象的原型 Object.setPrototypeof()
let person = {
getGreeting(){
return "hello";
}
}
let dog = {
getGreeting(){
return "woof!";
}
}
//person prototype
let friend = Object.create(person);
print(friend.getGreeting()); //hello
print(Object.getPrototypeOf(friend) == person); //true
//set prototypeOf dog
Object.setPrototypeOf(friend,dog);
print(friend.getGreeting()) //woof!
print(Object.getPrototypeOf(friend) == dog); //true
6: 简化原型访问的super引用,必须在简写方法的对象中使用Super引用
let person = {
getGreeting(){
return "hello";
}
}
let dog = {
getGreeting(){
return "woof!";
}
}
let friend = {
getGreeting(){
//return Object.getPrototypeOf(this).getGreeting.call(this) +" hi!";
return super.getGreeting() +" hi!";
}
}
Object.setPrototypeOf(friend,person);
print(friend.getGreeting())
print(Object.getPrototypeOf(friend) === person)
Object.setPrototypeOf(friend,dog);
print(friend.getGreeting())
print(Object.getPrototypeOf(friend) == dog)
7: 使用var let const解构声明变量,则必须提供初始化程序.
- 1: 如果不使用解构功能,则var let声明不强求提供初始化程序,但是const需要
- 2: 任何解构表达式尝试读取 null or undefined的属性时都是报错.
- 3: 读取type的属性并将其存储在变量localType中,let {type:localType,name:localName} = node
- 4: 可以嵌套读取
let node = {
type:"Identity",
name:"foo",
loc:{
start:{
line:1,
column:1
},
end:{
line:2,
column:2
}
}
}
let {loc :{end}} = node ;
print(end.line,end.column)
let a = 1,
b = 2 ;
[a,b] = [b,a]
print(a,b) //交换 a,b的值
// 复制数组
let colors = ["red","green","blue"];
let [...clone] = colors
print(clone)
print(colors.join(" "))
print(colors.concat(" "))
//应用场景1
function setCookie(name,value,{secure,path,domain,expire} = {}) //使用解构的话比较清晰
// ES6 之前的模拟 set and map
var set = Object.create(null);
set.foo = true
if(set.foo){
print("hello")
}
var map = Object.create(null)
map.foo = "bar";
print(map.foo)
// 若引用set, 集合中的弱引用如果是对象的唯一引用,则会被回收并且释放相应内存(不支持原始值,只支持引用类型)
let set = new WeakSet(),
key = {};
set.add(key);
print(set.has(key)); //true
set.delete(key);
print(set.has(key)); //false
//注意weakset: 不可迭代即不可以使用for..in (2)不能不报露任何迭代器例如keys and values (3)不支持forEach (4) 不支持size属性
// set and map底层都是Object.is判断相等的
let map = new Map();
map.set("title","Understanding js");
map.set("year",2016)
print(map.get("year"))
print(map.get("title"))
//默认初始化
let map = new Map([["title","Understanding js"],["year",2016]]);
//迭代map (value,key,ownermap) => print ...
map.forEach((v,k) => print(k+" -> "+v))
//使用weak map 存储私有数据
let Person = (function(){
let privateDate = new WeakMap();
function Person(name){
privateDate.set(this,{name:name});
}
Person.prototype.getName = function(){
return privateDate.get(this).name;
};
return Person;
}());
var p1 = new Person("shen");
var p2 = new Person("yang");
print(p1.getName())
print(p2.getName())
//新的迭代器: for ..of 循环,展开运算符(...) ,异步编程也可以使用迭代器
//ES5中写迭代器的写法, ES6中增加了 一个生成器对象,他可以让创建迭代器对象变得简单
function createIter(items){
var i = 0;
return {
next : function(){
var done = (i>=items.length);
var value = !done ? items[i++] : undefined;
return {done:done,value:value};
}
}
}
var iter = createIter([1,2,3])
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())
//生成器是一种返回迭代器的函数,通过function*来表示,函数中会用到新的关键字yield
function*createIter(){
yield 1;
yield 2;
yield 3;
}
function*createIter(items){
for(let i = 0;i<items.length;i++){
yield items[i];
}
}
var iter = createIter([1,2,3])
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())
//生成器对象的方法,
let o = {
*createIter(items){
for(let i =0;i<items.length;i++){
yield items[i];
}
}
}
let iter = o.createIter([1,2,3])
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())
//由于生成器默认会为Symbol.iterator属性赋值,因此所有通过生成器创建的迭代器都是可迭代对象
//for-of 循环每执行一次都会调用可迭代对象的next方法
//访问默认迭代器
let values = [1,2,3]
let iter = values[Symbol.iterator]();
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())
//检测对象是否可迭代
//默认开发者定义的对象都是不可迭代对象,但如果给Symbol.iterator属性添加一个生成器,者可以变成一个迭代对象
let collection = {
items:[],
*[Symbol.iterator](){
for(let item of this.items){
yield item;
}
}
}
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);
for(let x of collection){
print(x)
}
// 内建迭代器: entries() values() keys()
let data = new Map([["title","understanding ES6"],["format","ebook"]]);
for(let [key,value] of data){
print(key+" -> "+value);
}
//第二次调用next()方法传入的值为4,他会被赋值给变量first,函数继续执行
function *createIter(){
let first = yield 1;
let second = yield first + 2;
yield second + 3;
}
let iter = createIter();
print(iter.next());
print(iter.next(4));
print(iter.next(5));
print(iter.next());
//yield语句也可以抛出异常
function *createIter(){
let first = yield 1;
let second;
try{
second = yield first + 2;
}catch(ex){
second = 6;
}
yield second +3;
}
let iter = createIter();
print(iter.next()) // { value: 1, done: false }
print(iter.next(4)) // { value: 6, done: false }
print(iter.throw(new Error("Boom!"))) //{ value: 9, done: false }
print(iter.next()) //{ value: undefined, done: true }
// yield 遇到 return 也会提前返回
// 在某些情况下,需要两个迭代器合二为一,这时可以创建一个生成器,再给yield语句添加一个星号,就可以将生成数据的过程委托给其他生成器.
function *createNumber(){
yield 1;
yield 2;
}
function *createColor(){
yield "red";
yield "green";
}
function *createCombinIter(){
yield *createNumber();
yield *createColor();
yield true;
}
var iter = createCombinIter();
print(iter.next()) //{ value: 1, done: false }
print(iter.next()) //{ value: 2, done: false }
print(iter.next())//{ value: 'red', done: false }
print(iter.next())//{ value: 'green', done: false }
print(iter.next())//{ value: true, done: false }
print(iter.next())//{ value: undefined, done: true }
//简单任务执行器: 由于执行yield语句会暂停当前函数的执行过程并等待下一次调用next()方法,因此可以创建一个函数,在函数中调用生成器生成相应的迭代器,从而在不用回调函数的基础上实现异步调用next方法
function run(taskDef){
//创建一个无使用限制的迭代器
let task = taskDef();
let result = task.next();
//循环调用next函数
function step(){
//如果任务没完成,则继续完成
if(!result.done){
result = task.next()
step()
}
}
//开始迭代
step();
}
run(function*(){
print("1...");
yield;
print("2 ...");
yield;
print("3 ... ");
});
//任务执行器之间互相通信
function run(taskDef){
//创建一个无使用限制的迭代器
let task = taskDef();
let result = task.next();
//循环调用next函数
function step(){
//如果任务没完成,则继续完成
if(!result.done){
result = task.next(result.value)
step()
}
}
//开始迭代
step();
}
run(function*(){
let value = yield 1;
print("value: "+value); // 1
value = yield value + 3
print("value: "+value) // 4
//如果result.value是一个函数
function run(taskDef){
//创建一个无使用限制的迭代器
let task = taskDef();
let result = task.next();
//循环调用next函数
function step(){
//如果任务没完成,则继续完成
if(!result.done){
if(typeof result.value == "function"){
result.value(function(err,data){
if(err){
result = task.throw(err);
return;
}
result = task.next(data);
step();
})
}else{
result = task.next(result.value);
step();
}
}
}
//开始迭代
step();
}
let fs = require("fs");
function readFile(filename){
return function(callback){
fs.readFile(filename,callback);
};
}
run(function*(){
let contents = yield readFile("data.txt");
print(String(contents));
print("Done");
});