ES6機能の機能を本当に理解していますか?

みなさん、こんにちは。また会いましょう。

休日は一瞬で、年明けの初日は朝起きたくないので、遅刻しないように目を閉じて服を着ました。

大丈夫、大丈夫、要点をつかんで、元気を出してください!

序文

関数はすべてのプログラミング言語の重要な部分です。Es6が登場する前は、JavaScriptの関数構文はあまり変更されておらず、多くの問題とあいまいな慣行が残っており、一部の関数を実装するために多くのコードを作成する必要がありました。

関数パラメーターのデフォルト値

JavaScript関数には特別な場所があります。つまり、関数パラメーターで定義されているパラメーターの数に関係なく、任意の数のパラメーターを渡すことができます。ただし、場合によっては、パラメーターのみを入力できます。この場合でも、多くのロジックを書くとコードの冗長性につながります。幸い、Es6バージョンには関数のデフォルト値があります。

Es5コードとEs6コードを比較してみましょう

Es5はデフォルトパラメータを処理します

function person(name, age) {
    name = typeof(name) != "undefined" ? name : `蛙人${+ new Date()}`
    age = typeof(age) != "undefined" ? age : 24
    
}
person()

上記の例では、Es5はデフォルトのパラメーター値をこのように処理します。パラメーターが多い場合、このようなコードを記述すると非常に冗長になるため、Es6には関数パラメーターのデフォルト値があります。

Es6はデフォルトパラメータを処理します

function person(name = "蛙人", age = 24) {
    console.log(name, age)
}
person()  // 蛙人 24
person("张三", 30) // 张三 30
person(null, null) // null null

上記の例は、Es6で処理されるデフォルトのパラメーターです。コードが非常に単純化されていることがわかります。上記のコードは、パラメーターがnullで渡されていることを確認できます。デフォルトのパラメーターの場合、nullも有効な値です。この場合、関数パラメータが未定義の場合にのみ使用されます。デフォルト。

関数パラメーター式

デフォルトのパラメーター値に関して、最も興味深い機能は、非プリミティブ値がパラメーターに渡されること、またはデフォルトのパラメーターを函数またはとして定義できることです变量

function defaultName() {
    return "蛙人"
}
function person(name = defaultName()) {
    console.log(name)
}
person("张三") // 张三
person() // 蛙人

デフォルトパラメータの式は、関数person作成されるとすぐには実行されませんが、関数が呼び出されてパラメータが渡されないときに実行されることに注意してください。

上記の例では、パラメータが渡されない場合defaultNameデフォルト値の関数が呼び出されます

変数に渡されるデフォルトのパラメータを見てみましょう。

let defaultName = "蛙人"
function person(name = defaultName) {
     console.log(name)
}
person("张三") // 张三
person() // 蛙人
function person(name, nickName = name) {
     console.log(name, nickName)
}
person("张三") // 张三 张三
person("蛙人", "掘金蛙人") // 蛙人 掘金蛙人

上記の例では、前の関数が変数に置き換えられていることを除いて、最初のコードブロックをすべて理解できます。2番目のコードブロックのコードを見て、nickNameパラメーターのデフォルト値を最初のパラメーターnameパラメーターに設定します。これは、パラメーターのデフォルト値を参照するときに、前のパラメーターの値のみを引用できるようにするためです。関数パラメーターは定義された変数と同等です。背後にある変数は前の変数にアクセスできますが、現在のスコープ内でのみ、関数パラメーターは現在のスコープです。別の例を見てみましょう。

function person(name = nickName, nickName) {
     console.log(name, nickName)
}
person("张三") // 张三 张三

上記の例では、最初のパラメータのデフォルト値は2番目のパラメータです。このとき、2番目の変数を定義する前にアクセスすると一時的なデッドゾーンが発生するため、実行時にエラーがスローされます。一時的なデッドゾーンがわからない私の最後の記事を読むことができます。「一目でわかるvar、let、constの違い」

関数パラメーターのデフォルト値が引数に与える影響

関数のデフォルトパラメータを使用する場合、argumentsオブジェクトの動作は以前とは異なります。

Es5非厳密モードで引数を使用する

Es5非厳密モードでは、パラメータという名前の関数の変更がargumentsオブジェクトに反映されます。arguments取得されるのは、現在の関数の実際のパラメータです。arguments非厳密モードでは、正式なパラメータとマッピング関係があります。 、仮パラメータargumentsの変更は変更に続きます。

function test(a, b) {
    console.log(a == arguments[0]) // true
    console.log(b == arguments[1]) // true
    a = "a"
    b = "b"
    console.log(arguments) // ["a", "b"]
}
test(1, 2)

上記の例では、非厳密モードでは、名前付きパラメーターの変更がargumentsオブジェクトに同期的に更新されます。ときにaパラメータが変化し、それがにマップされますarguments[0]オブジェクト。

Es5strictモードで引数を使用する

ストリクトモードを見てみましょうarguments

 function test(a, b) {
    'use strict';

    console.log(arguments)  // [1, 2]
    b = 10
    console.log(arguments) // [1, 2]
}
test(1, 2)

上記の例は厳密モードです。パラメータを変更しbargumentsオブジェクトを再度出力すると、それはまだ初期値であることがわかります。厳密モードでJavaScriptargumentsオブジェクトの紛らわしい動作はキャンセルされます。パラメータがどのように変更されても、argumentsオブジェクトは変更されなくなります。

Es6の引数に対するデフォルトのパラメーター値の使用の影響

Es6では、関数がデフォルトのパラメーター値を使用する場合arguments、オブジェクトの動作はJavaScriptstrictモードの動作と一致します。

 function test(a, b = 2) {
    a = 12
    b = 10
    console.log(arguments) // [1]
}
test(1)

上記の例では、argumentsオブジェクトが実際のパラメーターを取得している[1]ため、argumentsオブジェクトが出力されます。実際のパラメーターパラメーターが値を渡すため、argumentsオブジェクトの値は1つだけであることがわかります。2番目のポイントを見るab、パラメーター値は変更されargumentsています、オブジェクトは変更されていません如果一个函数使用了默认参数值,那么arguments对象的行为都将与JavaScript中的严格模式下保持一致これは上記のとおりです

名前のないパラメータの処理

jsの関数パラメーターの数は任意です。渡される数が少ない場合、デフォルトパラメーターの機能により、関数宣言のコードを効果的に簡略化できます。より多くの番号が渡されると、Es6はより良いソリューションも提供します。

Es5で名前のないパラメータを取得する

function test(a, b, c) {
    console.log(arguments) // [1, 2, 3]
}
test(1, 2, 3)

上記の例でargumentsは、オブジェクトはすべてのパラメーターを取得することもできますが、2番目のパラメーターの後にすべてのパラメーターを取得する場合は、ループしてそれらを除外する必要があります。

Es6で名前のないパラメータを取得する

function test(...parmas) {
    console.log(params) // [1, 2, 3, 4]
}
test(1, 2, 3, 4)
function test(a, b, ...params) {
    console.log(params)
}
test(1, 2, 3, 4)

上記の例では、最初のコードブロックはEs6のすべてのパラメーターを実装していますが、それでもニーズを満たしていません。次に、達成する2番目のコードブロックのコードを見てください。2番目のパラメーターの後にすべてのパラメーターがあります。

名前のないパラメータへのEs6アクセスの欠点

まず、各関数は1つのget変数パラメーターのみを宣言でき、関数の最後にのみ配置できます。そうしないと、エラーが報告されます。

function test(...params, a, b) {
	
}
test()

上記の例では、エラーがスローされます。無数のパラメーターが宣言された後は、後でパラメーターを宣言し続けることはできません。

もう1つのポイントはsettersetter関数関数を受け取るだけであり、不定パラメーターとして書き込まれた後は配列になり、プログラムが異常になるため、オブジェクトリテラルで不定パラメーターを定義できないことです。

let obj = {
  set name(...params) {

  }
}

関数名属性

JavaScriptすべての機能が持つnameプロパティを、プロパティは関数名の文字列に格納されます。名前のない関数にはまだname属性があり、name属性値は空の文字列です。

function person() {}
let test = function() {}

console.log(person.name) // person
console.log(test.name) // test

上記の例では、person関数のname属性値は「person」であり、宣言時の関数の名前に対応しています。無名関数式test関数のname名前は、無名関数に割り当てられた変数に対応しています。

name属性の特殊なケース

もともと各関数のname名前は現在の関数名に対応していると思っていましたが、後で気づきました。関数の特殊なケースを見てみましょう

var person = {
    get getName() {
        return "蛙人"
    }
}
console.log(Object.getOwnPropertyDescriptor(person, 'getName').get.name)  // get getName

function test() {}
console.log(test.bind().name) // bound test

上記の例でperson.getName、これは値関数getterであるため、その関数名get getName関数の場合setter、名前には接頭辞が付きますsetbind関数を作成することにより、その名前の前に「bound」が付けられます。

矢印機能

Es6の矢印関数は、最も興味深い機能の1つです。矢印関数は、矢印を=>使用して関数定義する新しい構文ですが、従来のJavaScript関数は多少異なります。詳細については、次の点を参照してください。

  • ノーthissuperarguments
  • newキーワード呼び出すことはできません
  • プロトタイプなしprototype
  • this方向を変えることはできません
  • 繰り返される名前付きパラメーターをサポートしていません

矢印関数と従来の関数には、変更されていないname属性があります。

矢印関数の構文

let person = () => "蛙人"

// 相当于下代码

function person() {
	return "蛙人"
}

上記の例では、矢印関数の右側の式が評価されると、すぐに戻ります。

矢印関数パラメーター

let getName = val => val

// 相当于下代码

function getName(val) {
    return val
}

矢印関数にパラメータが1つしかない場合は、括弧を省略してパラメータ名を直接書き込むことができます。2つ以上のパラメーターを渡す場合は、括弧を使用する必要があります。次の例を見てください

let sum = (a, b) => a + b

// 相当于下代码

function sun(a, b) {
    return a + b
}

オブジェクトリテラルを返したい場合は、次のように書くことができます

let getObj = () => ({name: "蛙人", age: 24}) // {name: "蛙人", age: 24}

// 相当于下代码

function getObj() {
    return {
    	name: "蛙人",
        age: 24
    }
}

矢印機能にはこれがありません

矢印関数のthis値は、関数外の非矢印関数の値によって異なりますthis。上位層がまだ矢印関数である場合は、検索を続けます。見つからない場合thisは、windowオブジェクトです。

let person = {
    test: () => {
        console.log(this)
    },
    fn() {
        return () => {
            console.log(this)
        }
    }
}
person.test()  // window
person.fn()()  // person对象

上記の例では、矢印がないことがはっきりとわかりますthis。したがってthis、外側の非矢印関数関数のみが検索されます。

矢印関数にはargumentsオブジェクトがありません

同様に、矢印関数にはargumentsオブジェクトがありませんが、外側のレイヤーに矢印以外の関数のレイヤーがある場合arguments、次のように外側の関数のオブジェクトを検索します。

let test1 = () => console.log(arguments)  // 执行该函数会抛出错误


function test2(a, b, c) {
    return () => {
        console.log(arguments) // [1, 2, 3]
    }
}
test2(1, 2, 3)()

上記の例では、現在の矢印関数にargumentsオブジェクトがないことがはっきりとわかりますが、その外層に移動して、矢印関数ではない関数を見つけます。注意:箭头函数找arguments对象只会找外层非箭头函数的函数,如果外层是一个非箭头函数的函数如果它也没有arguments对象也会中断返回,就不会在往外层去找了次の例を見てください

function test(a) {
    return function() {
        return () => {
            console.log(arguments) // []
        }
    }
}
test(1)()()

上記の例でわかるように、内部の矢印関数は、外側のレイヤーで矢印関数ではない関数を見つけ、外側の関数にargumentsオブジェクトがあるかどうかに関係なく戻ります。それが非矢印関数である場合にのみ、外層が矢印関数である場合、それは外層を探し続けます。

矢印関数はnewキーワード宣言できません

let test = () => {}
new test() // 抛出错误,找不到constructor对象

矢印関数にはプロトタイプがありませんprototype

矢印関数にはプロトタイプがないことを忘れないでください。インタビュアーが尋ねる可能JavaScript性がありprototypeます。のすべての関数に属性がありますか?

let test = () => {}
test.prototype // undefined

矢印機能はthis方向を変えることができません

let person = {}
let test = () => console.log(this)

test.bind(person)()
test.call(person)
test.apply(person)

上記の例でthisポインティングを変更する方法はエラーをスローしませんが、無効であり、thisポインティングを変更することはできません

矢印関数は名前付きパラメーターを繰り返すことはできません

let sum = (a, a) => {} // 抛出错误,参数不能重复

あなたがそれが良いと思うなら、それと同じように!

おすすめ

転載: blog.csdn.net/weixin_44165167/article/details/113843495