thumb
2022-09-12 12:39:48.000

Phần 1: Kiểu dữ liệu, tham trị & tham chiếu, khai báo biến, scope và hoisting trong Javascript

1. Kiểu dữ liệu (Data type)

  • Có 2 kiểu chính: Kiểu nguyên thủy và object.

2. Kiểu nguyên thủy (Primitive)

  • Number: 1, 6, 10.2, …
  • String: ‘anh ben’, …
  • Boolean: true/false
  • Null
  • Undefined
  • Symbol (ES6)

  typeof undefined           // undefined
  typeof null                // object. Dù là object nhưng nó vẫn được xếp vào kiểu nguyên thủy nhé
  null === undefined         // false
  null == undefined          // true
  

undefined nghĩa là không có giá trị. undefined xuất hiện ở


  // Biến chưa khởi tạo giá trị
  let a
  console.log(a) // undefined
  // Thuộc tính không tồn tại trong object
  let people = { name: 'Duoc' }
  console.log(people.age) // undefined
  // Thiếu param
  function sum(a, b) {
    console.log(b)
  }
  sum(1) // log ra b là undefined
  // function không return hoặc return undefined
  function handle() {
    alert('XdevClass')
  }
  console.log(handle()) // undefined
  

null nghĩa là rỗng (khác với '' nghĩa là chuỗi rỗng), giá trị của nó là rỗng. null thường được dùng cho object mà không có giá trị như mong đợi.

Không thể truy cập thuộc tính của nullundefined


  function getName(value) {
    return value.name
  }
  // Lỗi
  getName(undefined) // TypeError
  getName(null) // TypeError
  

3. Kiểu Object

Tất cả những kiểu không thuộc kiểu dữ liệu nguyên thủy được coi là kiểu Object


  // Plain Object
  var people = { name: 'Anh Ben', age: 28 }
  // Array
  var products = ['Iphone', 'Samsung']
  // Regular Expression
  var regex = /ab+c/
  // Function cũng được coi là 1 object
  function sum(a, b) {
    return a + b
  }
  // But
  typeof sum === 'function' // true
  // null không được coi là object mặc dù
  typeof null === 'object' // true
  

Với cách khai báo kiểu dữ liệu nguyên thủy như trên thì ta đang khai báo kiểu constructor. Ngoài ra ta có thể tạo một object cho boolean, number, string bằng các wrapper object như String, Number, Boolean.


  var str = new String('Ben')
  console.log(typeof str) // object
  console.log(str) // String {"Ben"}
  str === 'Ben' // false
  var num = new Number(1994)
  var b = new Boolean(true)
  

Để lấy giá trị nguyên thủy từ các object trên thì ta dùng hàm valueOf()


  var str = new String('Ben') 
  str.valueOf() // 'Ben'
  

Chúng có thể đóng vai như một function để chuyển đổi về giá trị nguyên thủy


  String(1994) // '1994'
  Number('2022') // 2022
  Boolean(1) // true
  

4. Tham trị và tham chiếu

4.1 Tham trị

Khi giá trị thuộc kiểu dữ liệu nguyên thủy, biến sẽ chứa giá trị của biến đó.


  // So sánh bằng giá trị
  'abc' === 'abc' //true
  28 === 28 // true
  // Luôn luôn bất biến (immutable)
  var num = 1
  // Thêm thuộc tính name
  num.name = 'AnhBen'
  // Không hiệu nghiệm
  console.log(num.name) // undefined
  

4.2 Tham chiếu

Khi gán hoặc sao chép dữ liệu thuộc kiểu object thì biến đó chỉ lưu địa chỉ của giá trị đó trên vùng nhớ. Nó không lưu giá trị được gán.


  // So sánh bằng tham chiếu
  {} === {} // false
  var names1 = ['Ben']
  var names2 = ['Ben']
  names1 === names2 // false
  // Có thể thay đổi (mutate)
  var people1 = {name: 'AnhBen'}
  var people2 = people1
  people2.name = 'BenAnh'
  console.log(people1) // {name: 'BenAnh'}
  

5. Truthy và Falsy

Truthy và falsy là những giá trị mà Javascript khi ép về kiểu boolean sẽ cho ra true hoặc false. Giống như dùng Boolean(value) để ép kiểu vậy.

Các giá trị được cho là truthy: Chuỗi khác rỗng, số khác 0 và tất cả các object.

Vì thế: [] hay {} vẫn được cho là truthy


  Boolean({}) // true
  Boolean([]) // true
  

Các giá trị được cho là falsy: undefined, null, false, 0, NaN, ''

6. Khai báo biến, scope, hosting

6.1 var

var khi khai báo trong function sẽ có funtion scope, còn lại là global scope

Vì thế: [] hay {} vẫn được cho là truthy


  // function scope
  function click() {
    var name = 'Ben'
  }
  click()
  console.log(name) // ReferenceError: name is not defined
  // global scope
  if (true) {
    var age = 28
  }
  console.log(age) // 28
  

var còn có tính chất hoisting, nghĩa là khai báo ở đâu đi nữa thì cũng được đưa lên đầu tiên


  console.log(name)
  var name = 'Ben'
  

sẽ được biên dịch thành


  var name
  console.log(name) // undefined
  name = 'Ben'
  

ngoài ra còn có thể khai báo lại


  var name = 'Ben'
  var name = 'Hoang'
  

6.2 let

let sẽ có block scope


  // Block scope
  if (true) {
    let name = 'Ben'
  }
  console.log(name) // ReferenceError
  // Không thể khai báo lại
  let age = 27
  let age = 28 // SyntaxError: Identifier 'age' has already been declared
  

6.3 const

const cũng như let đều có block scope. Khi khai báo biến bằng const với kiểu dữ liệu nguyên thủy, thì biến đó sẽ không thể cập nhật giá trị mới.


  // Không thể gán lại giá trị mới với giá trị nguên thủy
  const name = 'Ben'
  name = 'Kane' //TypeError: Assignment to constant variable.
  // Lưu ý với object
  const person = { name: 'Ben' }
  person.name = 'Ray'
  console.log(person) // {name: 'Ray'}
  

Lưu ý: Nếu bạn hỏi let và const có được Hoist hay không thì câu trả lời là có. let và const được Hoist nhưng bạn sẽ không thể truy cập chúng trước khi chúng thực sự được khai báo.

6.4 scope

Có 3 loại scope

  • Global Scope
  • Function Scope
  • Block Scope.

6.5 hoisting

Ngoài các trường hợp trên thì hoisting còn xuất hiện với khai báo hàm (Function Declaration)

Với cách này thì function được Hoisting. Và Javascript cho phép chúng ta gọi một hàm trước khi hàm đó được khai báo.


  hoisted() // Output: "This function has been hoisted."
  function hoisted() {
    console.log('This function has been hoisted.')
  }
  
Share: