1. Kiểu dữ liệu (Data type)
- Có 2 kiểu chính: Kiểu nguyên thủy và object.
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 null
và undefined
function getName(value) {
return value.name
}
// Lỗi
getName(undefined) // TypeError
getName(null) // TypeError
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
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
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'}
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
, ''
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'
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
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.
Có 3 loại scope
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.')
}