JavaScriptは間違えやすい知識点を整理します.

5531 ワード

前言
本論文はJavaScriptを勉強している間に収集して整理したいくつかの間違えやすい知識点であり、それぞれ変数の作用領域から、タイプ比較、this指向、関数パラメータ、クローズド問題及び対象コピーと賦値の6つの方面で、浅い紹介と解説を行います.中にはES 6の知識点も含まれています.
JavaScript知識ポイント
1.変数スコープ
var a = 1;
function test() {
    var a = 2;

    console.log(a); // 2
}

test();
上の関数のスコープでは、aを宣言して割り当てられており、consolieの上にあるので、近くの原則に従って出力aは2に等しい.
var a = 1;
function test2() {
    console.log(a); // undefined

    var a = 2;
}

test2();
上の関数のスコープでは、aを宣言して与えましたが、consoneの下では、a変数が引き上げられ、出力時に宣言されましたが、まだ値が与えられていないため、undefinedが出力されます.
var a = 1;
function test3() {
    console.log(a); // 1
    
    a = 2;
}

test3();
上の関数作用領域においてaは再割り当てされ、再宣言されず、consoneの下に位置しているので、グローバル作用領域のaが出力される.
let b = 1;
function test4() {
    console.log(b); // b is not defined

    let b = 2;
}

test4();
上の関数のスコープでES 6のletを使って変数bを再宣言しましたが、letはvarとは異なり、変数アップの機能がないので、エラーb is not definedを出力します.
function test5() {
    let a = 1;

    {
        let a = 2;
    }
    
    console.log(a); // 1
}

test5();
上の関数のスコープでは、letでaが1であることを宣言し、ブロックレベルのスコープでaが2であることを宣言した.なぜなら、consoneは関数内のブロックレベルのスコープ内にないので、1を出力する.
2.タイプ比較
var arr = [],
    arr2 = [1];

console.log(arr === arr2); // false
上の二つの異なる配列を比較して,consoneはfalseである.
var arr = [],
    arr2 = [];

console.log(arr === arr2); // false
上の2つの同じ配列の比較は、2つの別々の配列が等しくないため、consolieはfalseである.
var arr = [],
    arr2 = {};

console.log(typeof(arr) === typeof(arr2)); // true
上にtypeofを利用して配列とオブジェクトを比較します.typeofがNULL、配列、オブジェクトのタイプを取得するのはすべてobjectなので、consoleはtrueです.
var arr = [];

console.log(arr instanceof Object); // true
console.log(arr instanceof Array); // true
instance ofを利用して、一つの変数がある対象のインスタンスに属するかどうかを判断します.JavaScriptでは配列も対象の一つであるため、二つのconsoneはtrueです.
3.this指向
var obj = {
    name: 'xiaoming',
    getName: function () {
        return this.name
    }
};

console.log(obj.getName());  // 'xiaoming'
上の対象方法の中のthisは対象自体を指すので、xiaomingを出力します.
var obj = {
    myName: 'xiaoming',
    getName: function () {
        return this.myName
    }
};

var nameFn = obj.getName;

console.log(nameFn()); // undefined
オブジェクト中のメソッドの値を上に変数を与えた場合、この方法のthisはobjオブジェクトを指すことなく、windowオブジェクトを指すので、consolieはundefinedとなります.
var obj = {
    myName: 'xiaoming',
    getName: function () {
        return this.myName
    }
};

var obj2 = {
    myName: 'xiaohua'
};

var nameFn = obj.getName;

console.log(nameFn.apply(obj2)); // 'xiaohua'
上の方もobjオブジェクト中の方法を変数nameFnに値付けしていますが、appy方式によりthisをobj 2オブジェクトに向けていますので、最終的なconsolieはxiahouaです.
4.関数パラメータ
function test6() {
    console.log(Array.prototype.slice.call(arguments)); // [1, 2]
}

test6(1, 2);
関数の中のargmentsクラスの配列オブジェクトを上から利用して、着信関数のパラメータ配列を取得するので、出力配列[1,2]が表示されます.
function test7 () {
    return function () {
        console.log(Array.prototype.slice.call(arguments)); //      ,   
    }
}

test7(1, 2);
上の方もargmentsを利用してパラメータを取得しますが、test 7(1,2)はreturnの関数を実行していませんので、出力はありません.test 7(1,2)(3,4)を実行すると[3,4]が出力されます.
var args = [1, 2];

function test9() {
    console.log(Array.prototype.slice.call(arguments)); // [1, 2, 3, 4]
}

Array.prototype.push.call(args, 3, 4);

test9(...args);
上にアラy.prototype.push.call()の方法を利用してargs配列に3と4を挿入し、ES 6延展オペレータ(...)を利用して配列を展開してtest 9に入るので、consoneは[1,2,3,4]です.
5.閉包問題
var elem = document.getElementsByTagName('div'); //       5 div

for(var i = 0; i < elem.length; i++) {
    elem[i].onclick = function () {
        alert(i); //   5
    };
}
上の方はよくあるクローズド問題です.divをクリックして、いつも5つの値をポップアップします.イベントをクリックした時、iの値はすでに5になりました.以下の方法で解決できます.
var elem = document.getElementsByTagName('div'); //       5 div

for(var i = 0; i < elem.length; i++) {
    (function (w) {
        elem[w].onclick = function () {
            alert(w); //    0,1,2,3,4
        };
    })(i);
}
結合クリックイベントの外部パッケージに、即座に関数を実行し、iをその関数に導入すればいいです.
6.対象コピーと割当
var obj = {
    name: 'xiaoming',
    age: 23
};

var newObj = obj;

newObj.name = 'xiaohua';

console.log(obj.name); // 'xiaohua'
console.log(newObj.name); // 'xiaohua'
上の方はObjオブジェクトをnewObjオブジェクトに割り当てて、newObjのname属性を変更しましたが、Objオブジェクトのname属性も改竄されています.これは実際にはnewObjオブジェクトが取得したのはメモリアドレスだけで、本物のコピーではなく、Objオブジェクトが改竄されています.
var obj2 = {
    name: 'xiaoming',
    age: 23
};

var newObj2 = Object.assign({}, obj2, {color: 'blue'});

newObj2.name = 'xiaohua';

console.log(obj2.name); // 'xiaoming'
console.log(newObj2.name); // 'xiaohua'
console.log(newObj2.color); // 'blue'
上にObject.assignを利用してオブジェクトの深度コピーを行うと、ソースオブジェクトが改竄される恐れがあります.Object.assign()方法は、任意の複数のソースオブジェクト自身のエニュメレート・属性を対象オブジェクトにコピーし、対象オブジェクトに戻ることができるからです.しかし、Object.assignは一級の属性コピーで、浅いコピーよりもずっと深くコピーしました.使う時、この問題に注意しなければなりません.
var obj3 = {
    name: 'xiaoming',
    age: 23
};

var newObj3 = Object.create(obj3);

newObj3.name = 'xiaohua';

console.log(obj3.name); // 'xiaoming'
console.log(newObj3.name); // 'xiaohua'
Object.create()法を用いてオブジェクトのコピーを行うこともでき、Object.create()法はプロトタイプオブジェクトと属性を指定した新しいオブジェクトを作成することができます.
おわりに
JavaScriptを学ぶのは長い過程で、一度に成功することができません.本論文で紹介したいくつかの内容はJavaScriptの学生がより深く理解し、JavaScriptの文法を把握するのを助けることができます.