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);