1. 程式人生 > 實用技巧 >js es6語法 es5的嚴格模式 es6 let const 塊級作用域 let和const和var的區別 解構賦值 物件的擴充套件 函式的擴充套件 箭頭函式

js es6語法 es5的嚴格模式 es6 let const 塊級作用域 let和const和var的區別 解構賦值 物件的擴充套件 函式的擴充套件 箭頭函式

一, ECMAScript和javascript的關係

ECMAScript是一個語法核心標準,javascript是語法的一種體現 。

二, es5的嚴格模式

1, 嚴格模式:

其實就是在一定程度上把語法規定的更標準,為了規範程式碼的標準性

2, 原因:

消除javascript 一些語法的不合理,不嚴謹,減少一些怪異行為

消除程式碼中的一些不安全的地方,保證程式碼的執行安全環境

提高編譯效率,增加執行速度

為了將來的javascript的標準做準備

3, 使用方式:

use strict放在所有程式碼的第一行,則整個指令碼就處於一種嚴格編譯的環境

如果這行不在整個程式碼塊的首行,沒有效果(非嚴格模式)

4, 使用範圍:

全域性範圍
"use strict"; // es5的嚴格模式啟動
a = 10;
console.log(a); //   a is not define
for迴圈內的嚴格模式
"use strict";  

for (i = 0; i < 5; i++) {
    console.log(i);
}
console.log(i);
自執行函式
var a = 10
;(function(){
    "use strict";  

    console.log(10);
})()
區域性範圍
function fn(){
"use strict"; // es5的嚴格模式啟動
b = 10;
console.log(b); // b is not defined
}
fn()

5, 失效的情況:

如果嚴格模式之前有程式碼,嚴格會失效,有空格,分號都不行,但是註釋沒問題

b = 20;
"use strict";
a = 10;
console.log(a);

6, 如果使用了嚴格模式。會影響arguments

"use strict";
function fn(a){
    arguments[0] = 2;
    console.log(a);
    console.log(arguments[0]);
}
fn(1);
// 變異  
 "use strict";
function fn(a){
    arguments[0] = 2;
    // 當使用alert的時候,嚴格模式失效
    alert(arguments[0]);
}
fn(1);

7, eval()函式計算javascript字串的,並把字串當做一個指令碼執行

如果引數是一個表示式,eval()函式執行表示式,如果引數是javascript的語句,eval()函式執行這個語句

console.log(eval("var a=10"));
eval("var a=10;console.log(a)");
console.log(eval("1+2")); // 3

console.log(eval("{b:2}"));
console.log(eval("({b:2})"));

eval("mytest()");

function mytest() {
    console.log(1);
}

// 嚴格模式
"use strict";
var eval = 10;
console.log(eval);

var obj = {}
obj.eval=10;
obj.a = eval;

function fn(eval){

}

8, 嚴格模式刪除系統內建屬性會報錯

"use strict";

/*   console.log(Object.prototype); // __proto__
  console.log(Function.prototype); */
// 內建屬性
delete Object.prototype;

9, JSON格式的資料

JSON.parse() :把字串格式的資料轉換成json物件格式的資料

JSON.stringify():把json格式的資料轉換為字串格式的資料

var arr = [1,2,3];
console.log(typeof arr);
console.log(JSON.stringify(arr));
console.log(typeof JSON.stringify(arr));

console.log('-------');
var arr1 = '[1,2,3]';
console.log(typeof arr1);
console.log(JSON.parse(arr1));
console.log(typeof JSON.parse(arr1));

// 注意:屬性名和屬性值全部要使用引號引起來
var json = '{"name":"zhangsan"}'

10, Object()擴充套件

建立一個物件

基於一個物件,建立一個新的物件,並可以對新隊形的屬性進行描述(操作)

語法:Object.create(person,decrtion);

person:原有的物件

decrtion:屬性描述 value:屬性值

writable:屬性是否可以修改新的屬性,預設值是false,不可以修改

configurable:是否可以刪除新的屬性,預設值是false,不可以刪除

ennumerable:是否可以列舉(遍歷)預設值是false,不可以列舉(遍歷)

建立一個物件:

var person = {
    name:'張三',
    age:20,
}

var me = Object.create(person);
me.name = '李四';
me.age = 30;
console.log(me); 

操作屬性

var me = Object.create(person, {
    sex: {
        value: '男',
        writable:true, // 可以更改屬性
        configurable:true,//可以刪除
        enumerable:true,// 可以遍歷(列舉)
    },
    sex1: {
        value: '男',
    }
})
// me.sex = '女'; 
delete me.sex;
// console.log(me.sex);

for(var attr in me){
    console.log(attr);
}

Object.defineProperties(object,descriptors)

這個方法直接在一個物件上定義新的屬性或者修改現有的屬性,並返回該duixaing

​ object:定義或修改的屬性的物件

​ get:作為該屬性的getter函式,如果沒有getter結果為undefined,函式返回值將被作為屬性的值

​ set:作為該屬性的setter函式,如果沒有setter結果為undefined,函式返回值將被作為屬性的值

var stus = {
    scores:[
        {
            name:'張三1',score:65,
        },
        {
            name:'張三2',score:65,
        },
        {
            name:'張三3',score:65,
        },
        {
            name:'張三4',score:65,
        },
        {
            name:'張三5',score:65,
        }
    ]
}

Object.defineProperties(stus,{
    total:{
        get:function(){
            // 宣告一個變數
            var t = 0;
            for(var i = 0; i<this.scores.length;i++){
                t += this.scores[i].score;
            }
            return t;
        },
        enumerable:true, // 可以遍歷
    }
})
console.log(stus.total);

三, es6簡介

1, let基本用法

es6新增了let命令,用來宣告變數,他的用法類似var,但是宣告的變數,只在let命令坐在的程式碼塊內生效

{
   let a = 10;
   var b = 20;
}
console.log(a); // is not defined
console.log(b);
// let宣告的變數只能在宣告的當前的作用域內被訪問

for迴圈特別適合使用let

for (let i = 0; i < 5; i++) {
    console.log(i);
}
console.log(i); // is not defined

2, 使用let不存在變數提升

var a = undefined
console.log(a); // undefined
var a = 10;

console.log(b);
let b = 20; // 'b' before initialization

3, 暫時性死區

只要塊級作用域記憶體在let命令,它宣告的變數就繫結這個區域,在在受外部影響

var temp = 123; // 全域性變數
if (true) {
    temp = '123';
    let temp; //'temp' before initialization
}

4, 比較隱祕的死區域

// 比較隱祕的死區域

function fn(x = y, y = 2) {
    return [x, y]; // 'y' before initialization
}
fn();

// 正常
function fn(x = 2,y = x){
    return [x, y];
} 
fn();

5, 不允許重複宣告

let b = 10;
let b = 30;
console.log(b);  // 報錯 不會覆蓋

 // 引數和變數重名
function fn(a){// a = 1;
    let a;
}
fn(1);

四, 塊級作用域

1, 為什麼需要塊級作用域

第一種場景
var tmp = new Date();
function f(){
    console.log(tmp); // 變數提升 
    if(false){
        var tmp = 'hello world'; 
    }
}
f(); 
第二種場景,用來計數的迴圈變數洩露為全域性變數
var s = 'hello';

for (var i = 0; i < 5; i++) {
    console.log(i);
}
console.log(i); // 5 資料洩露

es6裡面允許作用域的任意層巢狀

{{
    {{{{
        let a = 10
    }}}}
}}

es6裡面在內層塊級作用域可以宣告和外層的塊級作用域同名的變數

{
    {
        let a = 10;
        {
            let a = 20;
            console.log(a);
        }
        console.log(a);
    }
}

在es6裡面,塊級作用域內宣告的函式,建議或者說是最好使用字面量的方式宣告函式

if(true){
  let a = function(){

  }
}

if語句在嚴格模式下

"use strict"; // 全錯
if(true) 
    let a = 10;

if(true)    
    function fn(){}

2, const 基本用法

const宣告一個只讀的常量,一旦宣告,常量的值就不能在改變

不可變指的是指向值的地址不可變,而不是值不可變

for (const i = 0; i < 5; i++) {
      console.log(i);
  }

const obj = {
    name: 'lisi',
    age: 20
}

3, var let const 之間的區別

1、var有變數提升 let和const沒有變數提升

2、var沒有塊級作用域,let和const有塊級作用域

3、let和const指向的值和地址

let a = 10;
a = 20; // 
console.log(a);

const b = 10;
b = 20;
console.log(b);

const實際上保證的,並不是邊量的值不得改動,而是變數的那個記憶體地址所儲存的資料不得改動。

但對於複雜資料型別來說,變數指向的記憶體地址,儲存的只是一個指向實際資料的指標,const只能保證這個指標是固定的(即總時指向另一個固定的地址)。

五, 解構賦值

es6允許按照一定的模式,將陣列或物件中的資料提取出來,賦值給變數,這個過程叫做解構賦值。

1, 陣列的解構賦值

let [a, b, c, d] = [1, 2, 3, 4];  // 
console.log(a);

其他列子

let [a, b, c, d] = [1, 2, 3, 4];  // 
console.log(a);

let [foo,[[bar],baz]] = [1,[[2],3]]
console.log(bar);

let [, , third] = ['foo','bar','baz'];
console.log(third);

let [head,...tail] = [1,2,3,4];
console.log(head); // 1
console.log(tail); // [2, 3, 4]

如果解構不成功,值為undefined

let [foo,foo1] = [,2];
console.log(foo); // undefined

另一種情況就是不完全解構,等號左邊的模式,只匹配第一部分等號右邊的陣列,這種情況,結構依然可以成功

let [x, y] = [1, 2, 3];
console.log(x, y);

let [a, [b], d] = [1, [2, 3], 4];
console.log(a, b, d);

解構的時候,等號右邊不是陣列,報錯

let [foo] = false;

對於set結構,也可以使用陣列解構賦值

let [x,y,z] = new Set(['a','b','c']);
console.log(typeof x);

陣列解構賦值允許指定預設值

let [foo = true] = [];
console.log(foo);

let [x,y='b'] = ['a'];
console.log(x,y);

es6內部使用嚴格相等運算子(===)判斷一個位置是否有值,所以只有當一個數組成員嚴格等於undefined,預設值才生效

let [x = 1] = [undefined];
console.log(x);

// 預設值是null會直接賦值
let [y = 2] = [null];
console.log(y);

2, 物件解構賦值

解構賦值不僅僅可以用於陣列,也可以用於物件

物件的解構賦值

let {foo,bar} = {foo:'a',bar:'b'};
console.log(foo);

物件的解構賦值和陣列的解構賦值不一樣,陣列的元素是依次排列的,變數的值有位置決定,而物件的屬性沒有次序,變數必須與屬性同名,才能取到值

let {baz} = {foo:'aaa',bar:'bbb'};
console.log(baz); //undefined

物件的結構賦值,可以很方便的將現有的物件的方法,賦值給某一個變數

const { log } = console;
log('hello'); // 

如果變數名和屬性名不一致,必須這麼寫

// 如果變數名和屬性名不一致,必須這麼寫
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };

// console.log(baz);
// 相等
let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' }
console.log(bar);

與陣列一樣,物件解構也可以用於巢狀結構的物件

let obj = {
    p: [
        'hello',
        {
            y: 'world'
        }
    ]
}
let { p: [x, { y }] } = obj;
console.log(x, y);

注意:這種情況下 p 是模式,不是變數,不會被賦值,如果 p 作為也要作為變數賦值

let obj = {
p: [
    'hello',
    {
        y: 'world'
    }
]
}
let {p, p: [x, { y }] } = obj;
console.log(x, y);
console.log(p);   

物件也可以指定預設值

const { x = 3} = {};
console.log(x);

let {x,y=5} = {x:1};
console.log(x,y);

es6內部使用嚴格相等運算子(===)判斷一個位置是否有值,所以只有當一個物件成員嚴格等於undefined,預設值才生效

var {x = 3} = {undefined};
console.log(x);

var {x = 3} = {x:null};
console.log(x);

如果將一個已經宣告的變數用於解構賦值,使用的時候,必須得非常小心

let x;
{x} = {x : 1};
console.log(x);

// 正確方法  
let x;
({x} = {x : 1});
console.log(x);

3, 函式引數的解構賦值

函式的引數也可以解構賦值

function add([x, y]) {
    return x + y;
}
console.log(add([1, 2]));
[[1, 2], [3, 4]].map(([a, b]) => console.log(a + b));

引數也可以使用預設值

function add({ x = 0, y = 0 } = {}) {
    return [x, y];
}
console.log(add());

console.log(add({ x: 3, y: 8 }));

// 另一種寫法
function move({ x, y } = { x: 0, y: 0 }) {
    return [x, y];
}
console.log(move({ x: 3, y: 9 }));

模板字串

for (var attr = 0; attr < json.length; attr++) {

    var cur = json[attr]
    ul.innerHTML = `<li>
    <a href="${cur.url}">${cur.title}</a>
</li>`;
}

六, 物件的擴充套件

es6允許在大括號裡面,直接寫入變數和函式,作為物件的屬性和方法,這麼寫更簡潔

const foo = 'bar';
const baz = {foo};
console.log(baz); 

// 等同於
const baz = {foo:foo}

另外一種寫法

function f(x, y) {
    return { x, y }
}

//  等同於
function f(x, y) {
    return { x: x, y: y }
}

console.log(f(1,2)); // {x: 1, y: 2}

屬性名錶達式

Javascript定義物件的屬性,有兩種方法

// 方法一
obj.foo = true;
// 方法二
obj['a' + 'bc'] = 123;

es6裡面允許屬性名以表示式的形式存在,但是必須使用方括號[]

let propKey = 'foo';

let obj = {
[propKey]:true,
['h' + 'ello']:123
}

console.log(obj.hello);

另一種方式

let lastWorld = 'last world';

const a = {
    'first world':'hello',
    [lastWorld]:'world'
}

console.log(a['first world']);
console.log(a[lastWorld]);

表示式定義方法名

let obj = {
    ['h'+'ello'](){
        return 'h';
    }
}

console.log( obj.hello());

注意:屬性名錶達式和簡潔寫法,不能同時使用,會報錯

// 報錯
  const foo = 'bar';
  const bar = 'abc';
  const baz = { [foo] };

// 正確
const foo = 'bar';
const baz = { [foo]: 'abc' }
console.log(baz); // {baz:'abc'}

屬性名錶達式是一個物件,預設情況下回將物件轉為字串[object],這個要小心

const keyA = { a: 1 };
const keyB = { b: 2 };

 const myObject = {
     keyA:'valueA',
     keyB:'valueB'
 }

 console.log(myObject);

七, 函式擴充套件

es6新增了一種新的函式:ArrayFunction(箭頭函式)

es6允許使用“箭頭(=>)”定義函式

var f = v => v; // f:函式名  v:引數(形參)

// 等同於
var f = function(v){
    return v;
}

如果箭頭函式不需要引數或者需要多個引數,就使用()代表引數部分

// 沒有引數
var f = () => {return 5};
console.log(f());

// 定義引數
var sum = (num1, num2) => num1 + num2;
sum(10, 20); // 30

當代碼有兩條語句或者多餘兩條語句的時候,程式碼塊要放在{}

var sum = (num1, num2) =>{return  num1 + num2};
sum(10, 20); // 30

由於大括號{}之間的程式碼,會被解釋為程式碼塊,所以,如果箭頭函式直接返回一個物件,必須在物件的外面加上括號,否則會報錯

// 報錯
let getTemp = (id) => {
    id: id,
        name: 'Temp',
};  

// 正確
let getTemp = (id) => ({
    id: id,
    name: 'Temp',
});

console.log(getTemp('box'));

// 值是undefined
let foo = () => {a:1};
console.log(foo()); //undefined