日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

es6 初步深入学习

發布時間:2025/6/15 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 es6 初步深入学习 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

es6初步深入學習

es6前言(只作了解就好)

ECMAScript和JavaScript的關系

ECMAScript和JavaScript的關系是,前者是后者的規格,后者是前者的一種實現(另外的ECMAScript方言還有Jscript和ActionScript)。

檢測node環境對ES6的支持情況

阮一峰寫了一個ES-Checker模塊,用來檢查各種運行環境對ES6的支持情況。運行下面的命令,可以查看你正在使用的Node環境對ES6的支持程度。

sudo npm i -g es-checkeres-checker

babel轉碼器

ES6轉碼器,可以將ES6代碼轉為ES5代碼,從而在現有環境執行。es6在線編輯器/在線轉碼器。

babel stage

在es6標準出來之前,大家都會參與討論,把各自覺得好的語法加進去,便有了很多階段(準標準、草案、提案..)。stage-0是一個提案,里面基本包括大家討論的所有內容,stage-1 -- stage-3以此類推,stage-3基本確定要進入es6了。所以使用webpack的同學會看到,安裝的依賴基本都是babel-preset-stage-0。

babel-polyfill

本人之前開發中遇到過一個問題,array的includes方法(string也有),當時運行在chrome47環境下,整個頁面打不開,報錯(babel includes can not a function),在chrome52環境下支持。解決辦法--安裝babel-polyfill。最后在你的文件中import 'babel-polyfill'。

Babel默認只轉換新的JavaScript句法(syntax),而不轉換新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局對象,以及一些定義在全局對象上的方法(比如Object.assign)都不會轉碼。舉例來說,ES6在Array對象上新增了Array.from方法。Babel就不會轉碼這個方法。如果想讓這個方法運行,必須使用babel-polyfill,為當前環境提供一個墊片。

let和const

let用于聲明變量,const用于聲明常量。但是聊這個之前,我們還是簡單提提老生常談的問題吧---scope。

塊級作用域

在es5中是不存在塊級作用域的,一般我們聽得比較多的是函數作用域(定義在函數中的參數和變量在函數外部是不可見的)。

function getVal(boo) {if (boo) {var val = 'red'// ...return val} else {// 這里可以訪問 valreturn null}// 這里也可以訪問 val}

那么在es5中如何使用塊級作用域呢?js中在一個函數中定義的變量,當這個函數調用完后,變量會被銷毀,我們可以利用這種特性(閉包,the most important feature!!)。

function caniuse() { for(var i=0;i<10;i++){} console.log(i); //10} caniuse();function caniuse2() {(function() {for(var i=0;i<10;i++){}})()console.log(i) //i is not defined}caniuse2()

在es6中,任何一對花括號中(for,if)的語句集都屬于一個塊,在這之中定義的所有變量在代碼塊外都是不可見的,我們稱之為塊級作用域。

function getVal(boo) {if (boo) {let val = 'red'// ...return val} else {// 這里訪問不到 valreturn null}// 這里也訪問不到 val}

有了es6,上面閉包的寫法我們用es6可以不需要用到立即執行函數。

for(let i = 0; i < 10; i++){}

let

let聲明的變量只在他的代碼塊內有效

{let i = 9;console.log(i) //9}console.log(i) //ReferenceError: i is not defined function test1() {for(var i = 0; i < 10; i++) {setTimeout(function() {console.log(i) //10次10}, 1000)}}function test2() {for(let i = 0; i < 10; i++) {setTimeout(function() {console.log(i) //0-9}, 1000)}}function test3() {for(var i = 0; i < 10; i++) {(function(i) {setTimeout(function() {console.log(i) //0-9}, 100)})(i)}}test1()test2()test3()

不存在變量提升

腳本開始運行時,變量i已經存在了,但是沒有值,所以會輸出undefined。變量ii用let命令聲明,不會發生變量提升。這表示在聲明它之前,變量ii是不存在的,這時如果用到它,就會拋出一個錯誤。

console.log(i) //undefinedconsole.log(ii) //ReferenceError: ii is not definedvar i;let ii;

還有一些比較不容易發現的暫時性死區

function test1(y = 1, x = y) {console.log(x, y) // 1 1}function test2(x = y, y = 1) {console.log(x, y) //error}test1()test2()

不允許重復聲明

// 報錯function () {let a = 10;var a = 1;}

const

  • 用const聲明,常量的值就不能改變。

  • const一旦聲明變量,就必須立即初始化,不能留到以后賦值。

  • 只所在的塊級作用域內有效。(見let)

  • 不能變量提升,存在暫時性死區,只能在聲明的位置后面使用。(見let)

  • 在一個scope中不可重復declare。

const foo; // SyntaxError: Missing initializer in const declaration
  • 對于復合類型的變量,變量名不指向數據,而是指向數據所在的地址。const命令只是保證變量名指向的地址不變,并不保證該地址的數據不變,所以將一個對象聲明為常量必須非常小心。

const foo = {};foo.prop = 123;foo.prop// 123foo = {}; // TypeError: "foo" is read-onlyconst a = [];a.push('Hello'); // 可執行a.length = 0; // 可執行a = ['Dave']; // 報錯const foo = Object.freeze({});// 常規模式時,下面一行不起作用;// 嚴格模式時,該行會報錯foo.prop = 123;

小結

ES5只有兩種聲明變量的方法:var命令和function命令。ES6除了添加let和const命令,另外兩種聲明變量的方法:import命令和class命令。所以,ES6一共有6種聲明變量的方法。

Iterator(簡單說下,下次再仔細補充)

有三類數據結構原生具備Iterator接口:數組、某些類似數組的對象、Set和Map結構。Iterator是一種機制,為不同的數據結構提供可遍歷操作。可遍歷結構,我的理解是可以執行for...of。

Iterator作用:

  • 為各種數據結構,提供一個統一的、簡便的訪問接口

  • 使得數據結構的成員能夠按某種次序排列

  • ES6創造了一種新的遍歷命令for...of循環,Iterator接口主要供for...of消費。

Iterator的遍歷過程

var it = makeIterator(['a', 'b']);it.next() // { value: "a", done: false }it.next() // { value: "b", done: false }it.next() // { value: undefined, done: true }function makeIterator(array) {var nextIndex = 0;return {next: function() {return nextIndex < array.length ?{value: array[nextIndex++]} :{done: true};}};}

for...of

let arr = [2,3,4,,7,8]for(let val of arr) {console.log(val) //2,3,4,undefined,7,8}for(let k in arr) {console.log(k) //"0" "1" "2" "4" "5",下標都是字符串哦}console.log(arr["2"]) //4let arr2 = {0: 'a', 1: 'b', 3: 'c'}for(let key of arr2) {console.log(key, arr2[key]) //arr2[Symbol.iterator] is not a function}for(let key in arr2) {console.log(key, arr2[key]) //"0" "a"//"1" "b"//"3" "c"}

Iterator的使用場合

  • 解構賦值(下一章)

  • 擴展運算符(spread, 方便,使用頻率很高。。。spread arguments in function)。

let [a, ...c] = [3, 5, 6, 7, 7, 9]console.log(a) //3console.log(c) //[5, 6, 7, 7, 9]let [e, ...f, g] = [3, 5, 6, 7, 7, 9]console.log(e) //3console.log(f) //[5, 6, 7, 7, 9]console.log(g) //errorvar str = 'hello';[...str] // ['h','e','l','l','o']let arr = ['b', 'c'];['a', ...arr, 'd'] // ['a', 'b', 'c', 'd']
  • yield*

let generator = function* () {yield 1;yield* [2, 4];yield 5}let iterator = generator()console.log(iterator.next()) //{"done": false, "value": 1}console.log(iterator.next()) //{"done": false, "value": 2}console.log(iterator.next()) //{"done": false, "value": 4}console.log(iterator.next()) //{"done": true, "value": 5}
  • 其他(for...of, Array.form(), Map(), Set())

變量的解構賦值(Destructuring)

解構賦值——我的字面理解是先分解結構,再匹配等號兩邊相對應的結構,如果解構成功給每個相對應地變量賦值,一般情況下如若不成功,就給對應的變量賦值undefined。

模式匹配

只要等號兩邊的模式相同,解構完全匹配。左邊的變量就會被賦予對應的值。

let [a, ...c] = [3, 5, 6, 7, 7, 9]console.log(a) //3console.log(c) //[5, 6, 7, 7, 9]let [x, y, ...z] = ['a'];x // "a"y // undefinedz // []

不完全解構

等號右邊的解構匹配左邊的,但是還有多余的值。如果右邊不具備Iterator接口,解構的過程中會報錯。

let [a, [b], d] = [1, [2, 3], 4];a // 1b // 2d // 4let [foo] = 1;let [foo] = false;let [foo] = NaN;let [foo] = undefined;let [foo] = null;let [foo] = {};

默認值

之前寫redux的時候,經常會用到默認值。

export function receiveCustomers({source=null, origin=null, start_at=null, end_at=null, keyword=null}) {return {type: types.CUSTOMERS_QUERY_CHANGE,source,origin,start_at,end_at,keyword}}
  • null/undefined

var [x = 1] = [undefined];x // 1var [x = 1] = [null];x // null
  • function

function aaa() {console.log(1)}let [a = aaa()] = [1] //a=1
  • 變量不能提升

let [x = y, y = 1] = []; // ReferenceError

對象解構

這個灰常常用。一般用法就行,不需要很怪異的寫法,可讀性差。總結幾點注意事項:

  • 如果要將一個已經聲明的變量用于解構賦值,必須非常小心。

  • 默認值生效的條件是,對象的屬性值嚴格等于undefined。

// 錯誤的寫法var x;{x} = {x: 1};// SyntaxError: syntax errorvar {x = 3} = {x: undefined};x // 3var {x = 3} = {x: null};x // null

對象的擴展

屬性的簡潔表示

這個比較常用,之前寫vuex的時候有使用到。用過vuex/redux的同學應該不會陌生

import {fn1, fn2} from 'action'//action.js里面有兩個方法fn1,fn2,最后 export {fn1,fn2}//等同于export{fn1: fn1, fn2: fn2}const { dispatch } = this.props//等同于const dispatch = this.props.dispatchvuex: {actions: {fn1,fn2}}//等同于vuex: {actions: {fn1: fn1,fn2: fn2}} function f(x, y) {return {x, y};}// 等同于function f(x, y) {return {x: x, y: y};}f(1, 2) // Object {x: 1, y: 2}

方法的簡寫

handleText = e => {this.setState({inputValue: e.target.value})};//等同于handleText: function(e) {...}

Object.assign

deep clone and shallow clone

JavaScript存儲對象都是存地址的,所以淺復制會導致 obj 和 obj1 指向同一塊內存地址,大概的示意圖如下。而深復制一般都是開辟一塊新的內存地址,將原對象的各個屬性逐個復制出去。

let obj = {0: "a", 1: "b", 2: "c"}let deepObj = JSON.parse(JSON.stringify(obj))//is not a really deep clone, but it works. let shallowObj = obj obj[3] = 'd'console.log(deepObj) //{0: "a", 1: "b", 2: "c"} console.log(shallowObj) //{0: "a", 1: "b", 2: "c", 3: "d"} console.log(obj) //{0: "a", 1: "b", 2: "c", 3: "d"}

JSON.parse(JSON.stringify(obj))這樣的使用方式并不是真正的深拷貝,因為它會丟失一些東西,一些obj的內在property之類的,
比如

obj_test1 = {a: 1,b: 2,get_a() {return this.a}}

這樣的一個obj,你用上面的方式會丟掉get_a,如果你定義一些prototype,也會丟失掉,或者如果包含一些dom元素之類的。但是我們多數時候只是用它來復制數據,不關心對象的方法之類的東西,這樣的話是夠用的。

常見作用

  • 對象拷貝(copy)

Object.assign方法實行的是淺拷貝,而不是深拷貝,如果源對象某個屬性的值是對象,那么目標對象拷貝得到的是這個對象的引用。之前自己的一個疑惑

let obj = {0: "a", 1: "b", 2: "c"}let objClone = Object.assign({}, obj) obj[3] = 'd' console.log(objClone) // {0: "a", 1: "b", 2: "c"} why the same, but not change

Javascript has five primitive data types:

  • Number

  • String

  • Boolean

  • Undefined

  • Null

  • Anything that doesn’t belong to any of these five primitive types is considered an object.

    primitive types are passed by value, while objects passed by reference.

    a = {a: 1, b: 2, c: 3, d: {aa: 11, bb: 22}}
    a1 = Object.assign({}, a, {a: 2})
    a1.d.aa = 'i am shllow copy'
    第二行是淺拷貝,a拷貝到a1了,并且把property a的值改成2了 (你覺得a.a會變成2么,為什么?)
    第三行把a1.d這個object理得aa這個property改了 (你覺得a.d.aa也會改么,為什么?)

    • 合并對象 (merge)

    Object.keys && Object.value

    ES5引入了Object.keys方法,返回一個數組,成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的key。Object.values返回value。

    Class

    不得不說,這是我從沒仔細看過的一部分,寫react的時候都是三板斧套路。。。
    特意留意一下super()。ES5的繼承,實質是先創造子類的實例對象this,然后再將父類的方法添加到this上面(Parent.apply(this))。es6中先創造父類的實例對象this(所以必須先調用super方法),然后再用子類的構造函數修改this。

    class Teachers extends React.Component {constructor(props, context) {super(props, context)}componentDidMount(){const { siteId, dispatch } = this.propsif (siteId) {dispatch(fetchTeachersList(siteId))}}componentWillReceiveProps(nextProps) {const { siteId, dispatch } = this.propsif (nextProps.siteId !== siteId) {dispatch(fetchTeachersList(nextProps.siteId))}}}export default Teachers

    搭配Object.assign()

    class Point {constructor(){// ...}}Object.assign(Point.prototype, {toString(){},toValue(){}});

    不存在變量提升

    new Foo(); // ReferenceErrorclass Foo {}

    class表達式

    Class表達式,可以寫出立即執行的Class。

    let person = new class {constructor(name) {this.name = name;}sayName() {console.log(this.name);}}('張三');person.sayName(); // "張三"

    this指向和箭頭函數

    箭頭函數很方便,解決了之前es5遺留下來的問題(繼承,this作用域)。箭頭函數沒有它自己的this值,箭頭函數內的this值繼承自外圍作用域。

    //es5中, var self = this;這樣的代碼你肯定常見,es6箭頭函數中不用鳥var obj = {field: 'hello',getField: () => {console.log(this.field)}}obj.getField() // undefined,這時this是window,var obj = {field: 'hello',getField(){console.log(this.field)}}obj.getField() // hello,

    自己常用的拓展

    let arr = [1,2,3,4,5,6]let arr2 = arr.reduce( (init, prev, index) => {init.push(prev*prev); return init}, [] )console.log(arr2) //[1,4,9,16,25,36]

    想起之前寫的數組轉對象的方法

    警告 yield 關鍵字通常不能在箭頭函數中使用(except when permitted within functions further nested within it)。因此,箭頭函數不能用作Generator函數。

    Module

    js歷史上沒有標準的模塊化。在ES6之前,社區制定了一些模塊加載方案,最主要的有CommonJS和AMD兩種。前者用于服務器,后者用于瀏覽器。但是這些都只能在運行時起作用,es6的模塊化可以在編譯時就能確定模塊的依賴關系,以及輸入和輸出的變量。

    模塊功能主要由兩個命令構成:export和import。先拋出一個問題:以下兩行代碼有什么區別?

    import {message, menu} from 'antd' import message from 'antd/lib/message'

    export

    對外的接口名與模塊內部變量的關系

    export對外的接口名與模塊內部變量之間,建立了一一對應的關系。當export一個function時,語句輸出的接口,與其對應的值是動態綁定關系,即通過該接口,可以取到模塊內部實時的值。

    export 1; //error export var m = 1 //rightvar m = 1; export m//error export {m} //right

    import

    注意 import命令具有提升效果,會提升到整個模塊的頭部,首先執行。所以在文件中的任意位置,exort也一樣,不過利于可讀性,還是import寫在文件開頭,export寫在文件結尾好點。

    注意 import命令接受一個對象(用大括號表示),里面指定要從其他模塊導入的變量名。大括號里面的變量名,必須與被導入模塊(profile.js)對外接口的名稱相同。

    import {message, menu} from 'antd' import message from 'antd/lib/message'

    所以這之間的區別就是前者中括號里的變量名要與export出的接口名一致,后者message是隨意起的名字,可以不與export出來的變量名保持一致,它代表export default出來的接口。export default命令用于指定模塊的默認輸出。顯然,一個模塊只能有一個默認輸出,因此export deault命令只能使用一次。所以,import命令后面才不用加大括號,因為只可能對應一個方法。本質上,export default就是輸出一個叫做default的變量或方法,然后系統允許你為它取任意名字。

    模塊的整體加載

    import * as circle from './circle';console.log('圓面積:' + circle.area(4));console.log('圓周長:' + circle.circumference(14));

    總結

    以上是生活随笔為你收集整理的es6 初步深入学习的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 性感美女在线 | 日韩一级片在线播放 | 久操福利视频 | 成片免费观看视频 | 婷婷亚洲天堂 | 国产精品乱码一区二区三区 | 国产麻豆精品久久一二三 | 黄片毛片av | 日本精品免费在线观看 | 99在线成人精品视频 | 中文字幕在线观看线人 | 久久国产精品无码网站 | 国产黄色大片网站 | 精品一区二区三区四区五区 | 天堂久久一区 | 能看av的网址 | 国产亚洲综合av | 欧美性bbw| 中文字幕婷婷 | 2022av在线 | 久久黄网站 | 日在线视频 | 视频一区二区在线播放 | 国产亚洲精品码 | 桃花色综合影院 | 九九九九精品九九九九 | 久久成人激情 | 亚洲码视频 | 欧美一卡二卡三卡 | 性国产精品 | 男人靠女人免费视频网站 | 三级av在线播放 | 深夜网站在线观看 | 无码人妻精品一区二区蜜桃色欲 | jizz免费 | 日韩一区二区不卡 | 69er小视频 | 醉酒壮男gay强迫野外xx | 性欧美日韩 | 九九热免费在线 | 69亚洲精品久久久蜜桃小说 | 亚洲精品视频一区二区 | 加勒比av在线播放 | 人妻一区二区在线 | 欧美成人手机在线 | 午夜激情成人 | 久久久久久9999| 午夜影院体验区 | 日韩精品久久久久久久的张开腿让 | 成人性爱视频在线观看 | 欧美视频三区 | 欧美日韩在线观看视频 | 九九综合九九 | 天天干夜夜爽 | 亚洲午夜无码久久久久 | 国产精品免费无码 | 欧美一区亚洲二区 | 日韩一区二区三区在线免费观看 | 日本美女在线 | av在线电影观看 | 97视频播放| 小sao货cao死你 | 欧美一区二区三区激情视频 | 玖草视频在线观看 | 亚洲图片视频小说 | 中国无码人妻丰满熟妇啪啪软件 | 国产片淫乱18一级毛片动态图 | 人人射视频| 亚洲国产精品尤物yw在线观看 | 老司机久久| 999精品视频在线观看 | 国产精品VideoSex性欧美 | 天天爽夜夜| 日日操天天 | 九九热精彩视频 | 精品人妻少妇一区二区 | 亚洲一区二区三区视频在线 | 波多野一区二区 | 性欧美8khd高清极品 | 国产乱子伦一区二区 | 成人私密视频 | 精品九九九九 | 久久久久国产精品午夜一区 | 韩国av电影在线观看 | 黄色大片网站在线观看 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 日韩激情网站 | 韩国三级与黑人 | 国产精品久久中文字幕 | 国产裸体舞一区二区三区 | 天天干视频在线观看 | 欧美老女人视频 | 青青91| 日本久久综合网 | 久久成人网18网站 | 日韩精品专区 | 高清视频在线免费观看 | 在线成人欧美 | 在线播放成人 |