const和let定义的区别,相同点都是局部做用域,都不能重复声明,推荐使用const,若是变量会改变值的话再使用let,由于const能够提醒咱们这个不能被改变,const符合函数式变成,js编译器对const进行了优化,处理机制不一样。php
const定义的是内存中的块,若是定义的是对象,是能够修改的,可是若是是基本数据类型就不能修改了。es6
1. 解构模式,解构的内部变量是怎么声明的,前面是什么声明的就是什么声明的,如:ajax
function test(){数组
return {a: 123, b: 345};promise
}浏览器
const {a,b} = test();数据结构
这里的, a,b就是用const声明的闭包
若是是数组是这种写法app
const s = ['🍌', '🍊', '🍎'];async
const [c, d, e] = s;
函数参数默认值,参数的解构,扩展运算符
2. 字符串新增的方法:
s.startsWith(), s.endsWith(),s.includes()....
解析字符串模版的方法,两个参数都是数组
const s = 'hello';
const e = 'world';
const c = test`foor ${s} ${e} bar`; //加了()就是直接传的参数,没有第二个参数了
function test(strs, ...values){ //...扩展运算符
console.log(values); //arr
console.log(strs); //arr
}
strs的值是: ["foor ", " ", " bar"]
0:"foor "
1:" "
2:" bar"
至关于中间的两个变量将字符串分割成了三部分
3. 数组新增的方法
Array.from(str| arguments)
...扩展运算符的应用
const s = 'dfhajf';
const arr = Array.from(s);
const arr1 = [1,2,...s];
4. 对象
支持变量为key值,用 [ ] 包裹
Object.assign(),
属于浅拷贝,将属性合并到第一个对象上,复制对象:
var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 }
var o1 = { a: 1, b: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
属性会被后续参数中的相同属性覆盖。
下面是深拷贝的例子
obj1 = { a: 0 , b: { c: 0}}; let obj3 = JSON.parse(JSON.stringify(obj1)); obj1.a = 4; obj1.b.c = 4; console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
Object.assign()拷贝的是可枚举的属性,原型链中的属性和不可枚举的属性不能拷贝
原始类型会被包装成对象,根据自身的可枚举属性,若是不可枚举则不会被拷贝
var v1 = 'abc'; var v2 = 10; var v3 = Symbol('foo'); var obj = Object.assign({},v1, v2, null, undefined, v3); //null 和undefined会被忽略 //只有字符串的包装对象有可枚举属性 console.log(obj); // {0: a, 1: b, 2: c}
异常会打断后续拷贝任务,好比遇到只读属性的时候,
var target = Object.defineProperty({},'foo',{ value: 1, writable: false }) Object.assign(target, {bar:2},{foo2: 3,foo: 2, foo3: 4},{baz: 4}); console.log(target);
字面量的对象经过__proto__能够修改prototype的值
const drink = {
getDrink(){
return "pijiu"
}
}
const sunday = {
__proto__: drink,
}
Object.setPrototypeOf(sunday, drink); //和上面的代码等价
sunday.getDrink();
上面能够当作是继承,Sunday继承drink中的属性和方法,若是sunday想在内部调用drink中的话
继承 用super
Object.is() 判断两个值是否是相等
Object.is(NaN, NaN) //true
类的声明(class),es6实现了类的语法糖,可是和以前的声明仍是有区别,区别是:
a. 类的声明不会存在提高,至关于使用let和const声明的,真正执行语句以前,它们会一直存在与临时死区中;
b. 类中的全部方法都是不可枚举的,在以前的声明中没有这个限制,只有经过Object.defineProperty(obj, "name", {value: '99', enumerable: false})定义的方法才会是不可枚举的
c. 类的名称在声明的内部是不可修改的,在外部能够,由于在内部至关于用const声明的类名,而在外部至关于用let声明的名字
d. 类的声明只能经过new调用,普通调用会报错,由于每一个类都含有一个名为[[Construct]]的内部方法,经过关键字new调用那些不含有[[Construct]]的方法会报错;
e. 类声明中全部的代码自动运行在严格模式下,并且没法强行脱离严格模式
class Person{ constructor(name){ this.name = name; } sayName(){ console.log(this.name) } } let man = new Person('xx'); man.sayName();
下面是经过其余方式实现的,可见代码量的区别
let Person2 = (function(){ "use strict" const Person2 = function(name){ if(typeof new.target === 'undefined'){ throw new Error("必须经过关键字new调用构造函数"); } this.name = name; } Object.defineProperty(Person2.prototype, 'sayName',{ value: function(){ if(typeof new.target !== 'undefined'){ throw new Error("不可以使用关键字new调用该方法"); } console.log(this.name) }, enumerable: false, writable: true, configurable: true }) return Person2; })(); let woman = new Person2('ccc'); console.log(woman.sayName());
须要重点理解这个自执行函数,class是顺序执行的,并非new的时候才会调用,因此若是方法名或属性名是变量的话,在类声明下面再修改的话也不会生效了,使用的是类前面的值
new操做符的执行过程
1. 一个继承自prototype的新对象被建立,经过__proto__属性指向原型对象(prototype)
2. 使用指定的参数调用构造函数 (函数的名字),并将this绑定到新建立的对象
3. 由构造函数返回的对象就是new表达式的结果,若是构造函数没有返回值的话,就使用第一步的对象(通常状况下,都没有返回值,若是用户想返回不一样的对象能够本身定义,若是返回的不是对象呢,而是基本的数据类型,则忽略不计,仍然使用第一步的对象)
理解原型对象,原型链
每建立一个新函数就会生成一个对应的原型对象,经过prototype属性链接,prototype中存储的是指针
原型对象中会有一个constructor属性,这个属性存储的也是一个指针,指向新函数,因此这是一个循环的过程
建立对象,继承对象的新方法,super是语法糖,原理仍是原型链的继承,Object.create(newO, o.prototype)
5. 函数
增长了一个fn.name
箭头函数,的this是父级的this。
函数参数,默认参数直接在形参中指定
this的指向
6. Iterator, Generator
Iterator是一个数据结构,须要有next()一步一步向下执行,和Generator函数结合使用
var fn = function *(){
yield '22';
yield '33';
}
const result = fn();
result.next();
result.next();
result.next();
co模块是什么东东
for of 是有Symbol.iterator属性的对象才能使用
for in 有什么问题
for in遍历数组的话 遍历顺序有可能不是按照数组的实际顺序,会遍历数组的全部属性,包括原型上新定义的
for of只是遍历数组的值,不包括原型上的,还有自定义的非索引值
class类的定义,语法糖
class Person{
constructor(name){
this.name = name;
}
sayName(){
console.log(this.name)
}
}
class Teacher extends Person{
constructor(name){
super(name);
}
sayName(){
super.sayName();
...
}
}
7. Set, Map
Set的方法
let arr = new Set('12444');
arr.add('33');
arr.add('34');
arr.has('1');
arr.delete('34');
for(let data of arr){
console.log(data);
}
arr.clear();
console.log(arr.size)
Set能够直接去重,上面初始化的时候会生成 1 2 4,
Set是没有length属性的,有 size属性
Set没有key值,Map有key值,key值和value值能够是任何类型
Map的方法:
let map = new Map();
let fruit = {}, obj = function(){};
map.set(fruit,'32');
map.set( obj,'3233');
for(let item of map){
console.log(item); //打印的是完整的一项
}
map.get(fruit);
map.size;
map.delete(fruit);
map.clear();
数组去重的方法
let arr = [1,3,4,5,1,2,3,4,5];
let result = [...new Set(arr)];
对于es6及以后的语法,能够转换成es5的查看实现过程,也叫原理
module的两种不一样写法
a.
function test(){}
function gogo(){}
export test;
export gogo;
//export {test, gogo};
import {test, gogo} from 'index.js'
解构
b.
export default {test, gogo}
import data from 'index.js'
data.test();
data.gogo();
8. async awite promise fetch
(async(){
function promisefn(url){
return new Promise(function(resolve, reject){
$.ajax({
url: url,
success(res){
resolve(res);
},
error(){
reject('error');
}
})
})
}
const a1 = await promistfn('http://www.xxx.com/a');
const a2 = await promistfn('http://www.xxx.com/b');
let p = a1 + a2;
console.log(p);
})
async await 也是经过promise对象来实现的。
修饰器 decorator
function testable(target){
target.isTestable = true;
}
@testable
class myTestableClass{}
console.log(myTestableClass.isTestable);
修饰器对类的行为的改变,是代码编译时发生的,而不是运行时。这意味着,修饰器能在编译阶段运行代码
core-decorators.js库
浏览器有两个发请求的东西,一个是navigator.sendBeacon('a.php')作埋点用的,
一个是类ajax请求fetch('a.php')
symbol 惟一的
9. 数据类型
基本数据类型 6种了,Boolean,Number,String,null,undefined,Symbol
复杂数据类型统称为Object,新增的Set 和 Map 也是一个对象吧?
const obj = { name: 'www'};
obj.age = '333'; //不会报错,也就是能够添加,删除,修改属性值,可是不能改变对象的地址
obj = []; //会报错
10. label statement (语句优先)
11.自执行函数
操做符后面都是表达式
var b = 10;
(function b(){
b = 20;
console.log(b);
})();
console.log(b);
这个的运行结果想不通?
12.高阶函数,把函数看成参数或返回值的函数的函数
回调函数,闭包(函数,环境),惰性函数,柯里化(容许使用部分函数参数来生成函数),尾递归优化,反柯里化
ranmod
做用域的种类:
全局做用域,函数做用域,块级做用域(es6)
做用域链
变量与函数声明提早(变量提高)
this的指向,call,apply,bind
原型对象和原型链
构造函数的返回值,正常是不写返回值,但返回的是实例对象,特殊状况是写了返回值,return 简单的数据类型,返回的仍是实例,若是返回的是对象类型,那返回的就是这个对象
if(!("userName" in window)){
var userName = 'zhengzheng.xz';
}
console.log(userName); //undefined
变量提高
圆形对象中的constructor
Person.prototype.constructor === Person;
Function.prototype.constructor === Function;
Object.prototype.constructor === Object;
Object.constructor === Function; //这个是为何呢
题:
var name = "global";
function A(name){
alert(name); //实参就是 变量赋值,至关于前面有一个var name = name; 阻止了下面的变量提高,由于直接赋值了
this.name = name;
var name = '1';
}
A.prototype.name = '2';
var a = new A('3');
alert(a.name);
delete a.name;
alert(a.name);
function fun(n,o){
console.log(o);
return {
fun: function(m){
return fun(m,n);
}
}
}
var a = fun(0);
a.fun(1);
a.fun(2);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);