ES 6ベース(一)
15780 ワード
ECMAScript(ECMAまたはESと略称する)とJavaScript(JSと略称する)の関係は何ですか?
ESは標準で、JSは実現です.
変数宣言
ES 5のvarにはどんな欠陥がありますか?
varは変数を繰り返し宣言することができます.問題は他の人が宣言した変数を上書きすることです.var宣言変数の変更変数のスコープを制限できませんでした.
JSのスコープは大域作用域global scopeと関数機能領域function scopeの2種類だけで、ブロックレベル作用領域はありません.したがって、JSのコードブロックにおいてvar宣言を使用する変数のスコープは、いずれもグローバルスコープに属する.
キーワードletを使って変数を宣言します.
let宣言の変数は修正可能なlet宣言の変数です.let discount=10を繰り返し宣言できません./スコープはグローバルlet discount=100;/Uncaugt SyntxErrror:Identifer'discount'has already been declared let宣言の変数は、ブロックレベルの作用領域block scope let count=5を持つ.let discount=10;//グローバルif(count){let discount=100;/作用領域はブロックレベル}consosolone.logn(discount)//10キーワードを使ったconst宣言の定数
const声明の定数は、修正されてはいけないconst pi=3.14である.pi=3.1415;//Uncaught Type Error:Asignment to constant variable.const声明を使用しているのが対象(引用)であれば、対象のメンバー属性を変更することができますが、そのまま参照ポインタが指すアドレスです.
ES 6でlet宣言を使用した変数の値は修正が可能であり、const宣言を使用した定数の値は修正が禁止されている.
ES 5にはブロックレベルのスコープがなく、関数スコープだけがあります.
ES 5のvar宣言変数を使用して、ブロックレベルの作用領域が不足しているため、問題が発生しました.
関数クローズドを使用して、ブロックレベルのスコープ問題を解決します.
letおよびconstを使用して、すぐに関数式(IIIIFreedial tely-Invoked Function Expression)を実行し、すぐにプライベート変数を生成するために関数式を実行します.
ES 5でvar宣言を使用する変数のため、グローバルスコープを汚染しやすくなります.例えばJSのwindowオブジェクトはnameの属性を持っています.varを直接利用してグローバル変数nameを定義すれば、windowオブジェクトのname属性を直接カバーします.
例えば、forサイクルでよくある問題
ES 6では、コードブロック内でletまたはconstを使用して変数を宣言する前に変数は使用できません.文法的には、一時的なデッドゾーン(TDZ、Temporal Dead Zone)と呼ばれています.
var宣言の変数を使うと変数が上昇します.
割り当て値
表式の左右の構造は同じ表式でなければなりません.右側は値宣言と割り当てでなければなりません.
//ES 5分配値
ES 6新規方法starts WithとendsWith ES 6に文字列テンプレートString.starts Withを追加しました.
starts Withは、パラメータ文字列が元の文字列の先頭にあるかどうかを示し、ブール値を返します.
string.starts With(substring[,searchPos]]):bootlean例えば、URLアドレスの正当性を検証する.
//右揃え
従来の文字列のつづり合わせが正常に行われませんでした.伝統的な文字列の挿入ができませんでした.変数の伝統的な文字列のつづり合わせが友好的ではない処理のための単引用符と二重引用符が互いに嵌め合いました.ES 6テンプレート文字列は一対の逆引用符を使ってテンプレート文字列を定義します.
配列分解Aray Destructuring
ES 6は、一定のパターンに従って、配列から値を抽出し、変数を定義し、その割当値を定義することができます.これはすなわち、構造を解除します.
indexOf方法は、配列に要素が含まれているかどうかを判断します.
-1と要素のインデックス位置を返します.意味が足りないかどうかはNaN要素が含まれているかどうかを判断できません.
includiesメソッドの1番目のパラメータは、クエリの対象文字列includes方法の2番目のパラメータは、判断の開始インデックス位置includes方法の2番目のパラメータは負であり、右から数えても良いが、検索方向は変更されず、依然として左から右に向かって検索方向が変わります.
Aray.mapマッピング
//配列内のすべての要素を2倍にする
array.reduce(calback,[initial Value])reduce方法のアキュムレータ関数calbackは4つのパラメータを受け入れる.
Function calback(preValue,curValue,index,array)preValue初期値または前回のコールバック関数の戻り値curValue現在の要素値index現在のインデックスarrayは、reduce方法の配列を呼び出す.
ESは標準で、JSは実現です.
変数宣言
ES 5のvarにはどんな欠陥がありますか?
varは変数を繰り返し宣言することができます.問題は他の人が宣言した変数を上書きすることです.var宣言変数の変更変数のスコープを制限できませんでした.
JSのスコープは大域作用域global scopeと関数機能領域function scopeの2種類だけで、ブロックレベル作用領域はありません.したがって、JSのコードブロックにおいてvar宣言を使用する変数のスコープは、いずれもグローバルスコープに属する.
var price = 100;
var count = 5;
if(count > 3){
var discount = price * 0.5;
console.log(discount);//50
}
console.log(discount);//50
function fn(){
var cnt = 5;
console.log(cnt);
}
fn();//5
console.log(cnt);//Uncaught ReferenceError: cnt is not defined
ES 6には2つの定義変数があります.それぞれconstとletキーワードです.キーワードletを使って変数を宣言します.
let宣言の変数は修正可能なlet宣言の変数です.let discount=10を繰り返し宣言できません./スコープはグローバルlet discount=100;/Uncaugt SyntxErrror:Identifer'discount'has already been declared let宣言の変数は、ブロックレベルの作用領域block scope let count=5を持つ.let discount=10;//グローバルif(count){let discount=100;/作用領域はブロックレベル}consosolone.logn(discount)//10キーワードを使ったconst宣言の定数
const声明の定数は、修正されてはいけないconst pi=3.14である.pi=3.1415;//Uncaught Type Error:Asignment to constant variable.const声明を使用しているのが対象(引用)であれば、対象のメンバー属性を変更することができますが、そのまま参照ポインタが指すアドレスです.
const obj = {id:1, name:"alice"};
obj.id = 2;
console.log(obj);//{id: 2, name: "alice"}
オブジェクトの属性値を変更することが許可されていない場合は、Object.freezeメソッドを使用して凍結することができます.const obj = {id:1, name:"alpha"};
const o = Object.freeze(obj);
console.log(o);//{id: 1, name: "alpha"}
obj.id = 2;
console.log(obj);//{id: 1, name: "alpha"}
o.id = 3;//Attempt to assign to const or readonly variable
console.log(o);//{id: 1, name: "alpha"}
const宣言の定数は、const宣言の定数がブロックレベルの作用ドメイン変数と定数を持つことを繰り返してはならない.ES 6でlet宣言を使用した変数の値は修正が可能であり、const宣言を使用した定数の値は修正が禁止されている.
let i = 1;
i = 10;
console.log(i);//10
const PI = 3.14;
PI = 3.14159;//Uncaught TypeError: Assignment to constant variable.
ES 5においてvar宣言を使用する変数は、繰り返し割り当てられます.var i = 1;
console.log(i);//1
var i = 10;
console.log(i);//10
ES 6でlet宣言を使用する変数は、繰り返し宣言を禁止します.let i = 1;
let i = 10;//Uncaught SyntaxError: Identifier 'i' has already been declared
ES 6においてconst宣言を使用する定数禁止宣言を繰り返します.const PI = 3.14;
const PI = 3.14;//es6.js:2 Uncaught SyntaxError: Identifier 'PI' has already been declared
ブロックレベルのスコープES 5にはブロックレベルのスコープがなく、関数スコープだけがあります.
ES 5のvar宣言変数を使用して、ブロックレベルの作用領域が不足しているため、問題が発生しました.
js
window.onload = function(){
var btns = document.getElementsByTagName("button");
for(var i=0; i<btns.length; i++){
btns[i].onclick = function(){
alert(i);
}
}
}
問題:毎回3を出力します.関数クローズドを使用して、ブロックレベルのスコープ問題を解決します.
js
window.onload = function(){
var btns = document.getElementsByTagName("button");
for(var i=0; i<btns.length; i++){
(function(i){
btns[i].onclick = function(){
alert(i);
}
})(i);
}
}
ES 6のlet宣言を使用する変数は、ブロックレベルのスコープを有します.
es6
window.onload = function(){
let btns = document.getElementsByTagName("button");
for(let i=0; i<btns.length; i++){
btns[i].onclick = function(){
alert(i);
}
}
}
IIIIFはすぐに関数式を実行します.letおよびconstを使用して、すぐに関数式(IIIIFreedial tely-Invoked Function Expression)を実行し、すぐにプライベート変数を生成するために関数式を実行します.
ES 5でvar宣言を使用する変数のため、グローバルスコープを汚染しやすくなります.例えばJSのwindowオブジェクトはnameの属性を持っています.varを直接利用してグローバル変数nameを定義すれば、windowオブジェクトのname属性を直接カバーします.
console.log(name, window.name);
var name = "junchow";
console.log(name, window.name);//junchow junchow
すぐに関数式を実行すると、大域変数の汚染を効果的に回避し、変数を私有化することができます.console.log(name, window.name);//"" ""
(function(){
var name = "junchow";
console.log(name, window.name);//junchow ""
})();
console.log(name, window.name);//"" ""
, , 。
const name = "junchow";
console.log(name, window.name);//junchow ""
let name = "junchow";
console.log(name, window.name);//junchow ""
{
const name = "junchow";
console.log(name, window.name);//junchow ""
}
奇妙なforサイクル例えば、forサイクルでよくある問題
for(var i=0; i<3; i++){
console.log(i);// 0 1 2
}
console.log(i);//3
for(var i=0; i<3; i++){
console.log(i);//0 1 2
setTimeout(function(){
console.log(i);// 3 3 3
},1000);
}
console.log(i);//3
ES 6のletを使って循環変数を宣言します.for(let i=0; i<3; i++){
console.log(i);//0 1 2
setTimeout(function(){
console.log(i);// 0 1 2
},1000);
}
console.log(i);//Uncaught ReferenceError: i is not defined
一時死地ES 6では、コードブロック内でletまたはconstを使用して変数を宣言する前に変数は使用できません.文法的には、一時的なデッドゾーン(TDZ、Temporal Dead Zone)と呼ばれています.
var宣言の変数を使うと変数が上昇します.
console.log(color);//undefined
var color = "red";
なぜundefinedですか?実際上のコードは以下の通りです.var color;
console.log(color);//undefined
color = "red";
JSにおける関数および変数の宣言は、関数の最上部に引き上げられます.JSにおける変数は、使用後に宣言されます.つまり、変数は先に使用されてから宣言されます.console.log(color);//Uncaught ReferenceError: Cannot access 'color' before initialization
let color = "red";
変数の割り当て割り当て値
表式の左右の構造は同じ表式でなければなりません.右側は値宣言と割り当てでなければなりません.
//ES 5分配値
var arr = [1,2,3];
var x = arr[0];
var y = arr[1];
var z = arr[2];
console.log(x, y, z);//1 2 3
//ES 6配列解除賦課値let [x, y, z] = [1, 3, 5];
console.log(x, y, z);//1 3 5
JSON分解賦課値let {id, name} = {id:1, name:"alpha"};
console.log(id, name);//1 "alpha"
文字列ES 6新規方法starts WithとendsWith ES 6に文字列テンプレートString.starts Withを追加しました.
starts Withは、パラメータ文字列が元の文字列の先頭にあるかどうかを示し、ブール値を返します.
string.starts With(substring[,searchPos]]):bootlean例えば、URLアドレスの正当性を検証する.
let url = "http://www.baidu.com";
let bool = url.startsWith("http://");
console.log(bool);//true
starts Withの2番目のパラメータは開始位置です.例えば、身分証番号を確認します.const identify = "51030019800730366x";
//
console.log(identify.startsWith("51"));//true
// 1980 ,startsWith
console.log(identify.startsWith("1980", 6));//true
startsWith
const str = "jack love mary";
console.log(str.startsWith("jack"));//true
console.log(str.startsWith("Jack"));//false
String.endsWith
endsWith , 。
let url = "[email protected]";
let bool = url.endsWith("@hotmail.com");
console.log(bool);//true
String.repeat
repeat(count) count
repeat(count) count
repeat(count) count Infinity
repeat(count) count NaN 0
repeat(count) count
console.log(`${'='.repeat(10)}`);//==========
console.log(`${'='.repeat(10.9)}`);//==========
console.log(`${'='.repeat(0)}`);//
console.log(`${'='.repeat(NaN)}`);//
console.log(`${'='.repeat("10")}`);//==========
console.log(`${'='.repeat(-10)}`);//Uncaught RangeError: Invalid count value
console.log(`${'='.repeat(Infinity)}`);//Uncaught RangeError: Invalid count value
例えば、文字列の右揃えを実現します.//右揃え
const pad = (string, length=0)=> `${' '.repeat(Math.max(length - string.length, 0))}${string}`;
console.log(pad("hello", 20));// hello
console.log(pad("world", 20));// world
テンプレート文字列従来の文字列のつづり合わせが正常に行われませんでした.伝統的な文字列の挿入ができませんでした.変数の伝統的な文字列のつづり合わせが友好的ではない処理のための単引用符と二重引用符が互いに嵌め合いました.ES 6テンプレート文字列は一対の逆引用符を使ってテンプレート文字列を定義します.
let obj = {id:1, title:"test"};
console.log(`id = ${id} title = ${title}`);
テンプレート文字列の適用const User = {
id:1,
name:"junchow",
date:"2019-08-28",
todos:[
{todo:"go to store", status:false},
{todo:"watch movie", status:true},
{todo:"running", status:true}
]
};
//テンプレート文字列は入れ子ができます.const template = `${User.todos.map(item=>`- ${item.todo}
`).join("")}
`;
console.log(template);
document.querySelector("#app").innerHTML = template;
const User = {
id:1,
name:"junchow",
date:"2019-08-28",
todos:[
{todo:"go to store", status:false},
{todo:"watch movie", status:true},
{todo:"running", status:true}
]
};
//テンプレート文字列は入れ子ができます.const template = `
${User.todos.map(item=>`
-
${item.todo}
${item.status===true?"done":"undo"}
`).join("")}
`;
console.log(template);
document.querySelector("#app").innerHTML = template;
ラベルテンプレート文字列function tag(template, ...args){
const html = args.map(arg=>`${arg}`);
let ret = "";
template.forEach((item, index) => ret +=`${item} ${html[index]}`);
return ret;
}
const id = 1;
const name = "junchow";
const sentence = tag`${id} ${name}`;
console.log(sentence);
行列配列分解Aray Destructuring
ES 6は、一定のパターンに従って、配列から値を抽出し、変数を定義し、その割当値を定義することができます.これはすなわち、構造を解除します.
const result = [1, "success"];
//const [code, message, data] = result;
//console.log(code, message, data);//1 "success" undefined
//const [code, ,data] = result;
//console.log(code, data);//1 undefined
//const [code, ...args] = result;
//console.log(code, args);//1 ["success"]
//const [code=0, message="", data={}] = result;
//console.log(code, message, data);//1 "success" {}
例えば、変数値を交換するlet x = 10, y = 20;
[x, y] = [y, x];
console.log(x, y);//20 10
Array.protype.includes()
ES 5配列は、配列内のある要素のインデックス位置を調べるためにAray.indexOf()方法を提供し、存在しない場合は-1を返します.indexOf方法は、配列に要素が含まれているかどうかを判断します.
-1と要素のインデックス位置を返します.意味が足りないかどうかはNaN要素が含まれているかどうかを判断できません.
const arr = ["alice", "card", 1, 2, NaN];
console.log("%s", arr.indexOf("alice"));//0
console.log("%s", arr.indexOf(0));//-1
console.log("%s", arr.indexOf(NaN));//-1
ES 6は、アレー中に指定要素が含まれているかどうかを判定するために、アレーを提供するAray.includes()方法を提供し、NaNを同様に有効にします.includiesメソッドの1番目のパラメータは、クエリの対象文字列includes方法の2番目のパラメータは、判断の開始インデックス位置includes方法の2番目のパラメータは負であり、右から数えても良いが、検索方向は変更されず、依然として左から右に向かって検索方向が変わります.
const arr = ["alice", "card", 1, 2, NaN, "alice"];
console.log("%s", arr.indexOf("alice"));//0
console.log("%s", arr.indexOf(0));//-1
console.log("%s", arr.indexOf(NaN));//-1
console.log("%s", arr.includes("junchow"));//false
console.log("%s", arr.includes("alice"));//true
console.log("%s", arr.includes("alice", 4));//true
console.log("%s", arr.includes("alice", -5));//true
ES 6に4つの関数が追加されました.それぞれマッピングmap、まとめreduce、フィルタリングfilter、循環forEachです.Aray.mapマッピング
//配列内のすべての要素を2倍にする
let arr = [11, 23, 43, 90];
let result = arr.map((x)=>x*2);
console.log(result);//[22, 46, 86, 180]
let arr = [89, 23, 31, 78];
let result = arr.map((x)=>{
if(x>=90){
return "A"
}else if(x>=80){
return "B";
}else if(x>=60){
return "C";
}else{
return "D";
}
});
console.log(result);//["B", "D", "D", "C"]
Array.prototype.reduce()
reduce方法は、1つの関数をアキュムレータとして受け入れ、初期値(オプション)を指定し、配列内の各値(左から右へ)を縮小し、最終的に1つの値として計算する.array.reduce(calback,[initial Value])reduce方法のアキュムレータ関数calbackは4つのパラメータを受け入れる.
Function calback(preValue,curValue,index,array)preValue初期値または前回のコールバック関数の戻り値curValue現在の要素値index現在のインデックスarrayは、reduce方法の配列を呼び出す.
let arr = [100, 200, 300];
// tmp item index
let total = arr.reduce((tmp, item)=>{
//100 200 1
//300 300 2
//console.log(tmp, item, index);
return tmp + item;
});
//console.log(total);//600
例えば:平均を求めるlet arr = [100, 200, 300];
//
let average = arr.reduce((tmp, item, index, arr)=>{
if(arr.length === index+1){
return (tmp+item)/index;
}else{
return tmp + item;
}
});
console.log(average);//300
例えば:階乗を求めるlet arr = [100, 200, 300];
//
let result = arr.reduce((preval, curval)=>{
return preval * curval;
});
console.log(result);//6000000
例えば、二次元配列は一次元配列に変換される.let arr = [
[1, 3, 5],
[2, 4, 6],
[10, 20, 30]
];
let result = arr.reduce((retval, current, index, arr)=>{
return retval.concat(current);
});
console.log(result);//[1, 3, 5, 2, 4, 6, 10, 20, 30]
たとえば、配列中の要素の出現回数を計算します.let arr = ["alice", "bob", "carl", "bob", "carl", "bob"];
let result = arr.reduce((retval, current, index, arr)=>{
if(current in retval){
retval[current]++;
} else{
retval[current] = 1;
}
return retval;
},{});
console.log(result);//{alice: 1, bob: 3, carl: 2}
たとえば、配列内の要素の出現回数を計算します.let arr = ["alice", "bob", "carl", "bob", "carl", "bob"];
let times = (arr, val)=>arr.reduce((retval, current)=>{
return current===val ? retval+1 : retval+0;
},0);
console.log(times(arr, "bob"));//3
たとえば、配列オブジェクト内の指定フィールドの値を取得します.let arr = [
{id:11, name:"alpha", status:1},
{id:20, name:"alice", status:0},
{id:34, name:"bob", status:1}
];
// id
let getField = (arr, field) => arr.reduce((preval, curval)=>{
preval.push(curval[field]);
return preval;
}, []);
console.log(getField(arr, "id"));//[11, 20, 34]
たとえば、配列の再結合let arr = ["alice", "bob", "carl", "bob", "carl", "bob"];
let dedupe = (arr)=>arr.sort().reduce((retval, current)=>{
if(retval.length===0 || retval[retval.length-1]!==current){
retval.push(current);
}
return retval;
},[]);
console.log(dedupe(arr));// ["alice", "bob", "carl"]
例えば、あるユーザーの単科の成績を求めて、重み付けの割合によってまとめた後の重み付けの値を求めます.//
let arr = [
{subject:"math", score:89},
{subject:"chinese", score:89},
{subject:"english", score:89},
];
//
let percent = {math:0.5, chinese:0.3, english:0.2};
//
let result = arr.reduce((preval, curval)=>{
return preval + curval.score *percent[curval.subject];
}, 0);
console.log(result);//89