7 khái niệm JavaScript cần biết

Giá trị # Tham chiếu

5 kiểu dữ liệu được lưu trữ ở dạng giá trị - primitive type:

  • Boolean
  • null
  • undefined
  • String
  • Number

Khi copy giá trị của biến này cho biến khác, 2 giá trị này hoàn toàn độc lập không có liên hệ gì với nhau

var x = 10;

var a = x;

a = a + 10;

console.log(a)
console.log(x)

3 kiểu dữ liệu được lưu trữ ở dạng tham chiếu - Object type:

  • Array
  • Function
  • Object

Nó không mang giá trị mà chỉ tham chiếu đến vùng lưu trữ của đối tượng đó trong bộ nhớ.

var arr = [];
arr.push(1);

var refArr = arr;

refArr.push(2);

console.log(arr, refArrr)

So sánh =====

Khi thực hiện so sánh = trên biến kiểu tham chiếu, trả về true khi cả 2 biến số cùng trỏ về một dùng nhớ chứ không phải so sánh giá trị của 2 biến.

var arrRef = ['Hi!'];
var arrRef2 = arrRef;

console.log(arrRef === arrRef2); // -> true

var arr1 = ['Hi!'];
var arr2 = ['Hi!'];

console.log(arr1 === arr2); // -> false

Scope - khu vực hoạt động, phạm vi lãnh thổ

Global Scope - công dân toàn cầu

Nếu là một biến có phạm lãnh thổglobal scope, điều đó có nghĩa anh ấy là công dân toàn cầu, hàng ngôi sao quốc tế, ai cũng biết anh ấy là ai.

var name = "luckyluu";

console.log(name); // luckyluu

function logName(){
    console.log(name);
}
logName(); // luckyluu

Local scope

Nếu anh bạn tên "biến" của chúng ta chỉ là vô danh tiểu tốt, local scope, thì anh ấy chỉ được biết đến bởi dân địa phương, nơi anh ấy đăng ký hộ khẩu thường trú.

// Global Scope
function someFunction() {
    // Local Scope #1
    function someOtherFunction() {
        // Local Scope #2
    }
}

// Global Scope
function anotherFunction() {
    // Local Scope #3
}
// Global Scope

Block scope

Những câu khai báo như if, switch, for, while không giống như function bình thường, anh bạn biến lúc này con được biết đến ở toàn tỉnh do nhà anh ấy nằm thuộc diện cocc

if (true) {
    // câu lệnh điều kiện 'if' không tạo ra một scope mới
    var name = 'Con ông If';
    // name vẫn là global scope
}

console.log(name); // logs 'Con ông If'

Trong ES6, để tránh sự nhập nhằn này, khai báo biến bằng let,const chớ có dại dùng var để khai báo.

if (true) {
    // name = global scope
    var name = 'Con ông If';
    // likes = local scope
    let likes = 'luckyluu';
    // skills = local scope
    const skills = 'JavaScript and PHP';
}

console.log(name); // 'Con ông If'
console.log(likes);
// Uncaught ReferenceError: likes is not defined
console.log(skills);
// Uncaught ReferenceError: skills is not defined

Hoisting

Một đặc điểm của Javascript, biến có thể được sử dụng trước, khai báo sau! Viết như sau là hoàn toàn hợp lệ trong javascript

// gán giá trị 5 cho biến x chưa được khai báo
x = 5;

console.log(x);

// khai báo biến x
var x;

Do đó luôn như khai báo biến trước khi sử dụng là nguyên tắc gối đầu của mọi frontend developer, nếu không có thể xảy ra trường hợp sau

var name = "Michael Jackson";
​
​function showCelebrityName () {
    console.log (name);
}
​
​function showOrdinaryPersonName () {
    name = "Johnny Evers";
    console.log (name);
}
showCelebrityName (); // Michael Jackson​​showOrdinaryPersonName (); // Johnny Evers​// biến toàn cục name giờ đây sẽ bị change giá trị thành Johnny Evers ​
showCelebrityName (); // Johnny Evers​
​
​// luôn nhớ khai báo biến bằng var,let,constfunction showOrdinaryPersonName () {
    var name = "Johnny Evers";
    console.log (name);
}

Thậm chí khi khai báo biến kèm giá trị cho nó mà không dùng từ khóa var, biến đó sẽ trở thành biến toàn cục

function showAge(){
    age = 90; // nực cười chưa
    console.log(age);
}

showAge(); // 90

console.log(age) // 90

Closure

Closure ám chỉ một cơ chế hoạt động, một function bên trong một function khác lại truy cập được các biến của function ngoài, nghĩa là nó vi phạm nguyên lý biến không cùng scope thì KO được dò xét lẫn nhau, chuyện này lại làm được nếu 2 function nó là cha con với nhau.

function showName (firstName, lastName) {var nameIntro = "Your name is ";function makeFullName () {return nameIntro + firstName + " " + lastName;
    }
    ​
    ​return makeFullName ();
}showName ("Michael", "Jackson");
// Your name is Michael Jackson

Như vậy chưa đủ quá đáng, nó còn có thể truy cập ngay cả khi function ngoài (cha) đã return

function celebrityName(firstName) {
  var nameIntro = "This celebrity is ";function lastName(theLastName) {
      return nameIntro + firstName + " " + theLastName;
  }
  return lastName;
}
​
​var mjName = celebrityName("Michael");var result = mjName("Jackson");
// This celebrity is Michael Jackson

Tận dụng đặc điểm này của closure function, tạm gọi là cha truyền con nối, lưu tham chiếu đến biến của function ngoài mà không lưu giá trị, ta có thể viết một function như class thế này

function celebrityID(){
    var celebrityID = 999;
    return{
        getID: function(){
            return celebrityID;
        },
        setID: function(theNewID){
            celebrityID = theNewID;
        }
    }
}

var myID = celebrityID();
myID.getID(); // return 999
myID.setID(567);
myID.getID(); // return 567

Đọc thêm chi tiết về bài viết clusure của mình trên mozilla.org