1. Số – Number
Không như nhiều ngôn ngữ lập trình khác, kiểu số thường chia ra làm nhiều loại như integer, short, long. float… Riêng Javascript chỉ có kiểu number
Số nguyên trong Javascript có độ chính xác đến 15 chữ số
var x = 999999999999999; // x sẽ là 999999999999999
var y = 9999999999999999; // y sẽ là 10000000000000000
Giới hạn của số thập phân là 17 chữ số, nhưng không phải việc tính toán số thập phân lúc nào cũng chính xác 100%. Tìm hiểu floating-point
var x = 0.2 + 0.1; // x sẽ bằng 0.30000000000000004
Để giải quyết điều này, chúng ta nên nhân nó thành số nguyên rồi thực hiện
var x = (0.2 * 10 + 0.1 * 10) / 10; // x sẽ bằng 0.3
Nếu cộng 2 số thì kết quả sẽ là số. Nhưng nếu chuỗi cộng với số thì kết quả là chuỗi. Vậy nên khi tính toán thì nên chuyển hết về dạng số
var x = "10";
var y = 20;
var z = x + y; // z sẽ là 1020 (một string)
2. NaN – Not a Number
NaN
là một giá trị trong Javascript dùng để xác định một số không phải là một số hợp lệ
var x = 100 / 'Apple' // x sẽ là NaN (Not a Number)
typeof NaN // returns "number"
// chúng ta có thể dùng function isNaN() để kiểm tra giá trị có phải là NaN hay không
isNaN(x) // return true
3. Infinity – Dương vô cực
Infinity
nghĩ là dương vô cực, -Infinity
nghĩa là âm vô cực
var x = 2 / 0 // x sẽ là Infinity
var y = -2 / 0 // y sẽ là -Infinity
typeof Infinity // returns "number"
4. Hexadecimal – Hệ thập lục phân
Nếu bạn biểu diễn bắt đầu bằng 0x
thì JS sẽ hiểu đây là hệ thập lục phân
var x = 0xff // x sẽ là 255
5. Một số phương thức hay dùng
toString(): Ép kiểu số về chuỗi
var x = 123
x.toString() // '123'
(123).toString() // '123'
toFixed(): Làm tròn
var x = 9.656;
x.toFixed(0); // returns 10
x.toFixed(2); // returns 9.66
x.toFixed(4); // returns 9.6560
x.toFixed(6); // returns 9.656000
Ép kiểu về số
Chúng ta có 3 cách
- Number() chuyển đổi giá trị về kiểu số
- parseInt() chuyển đổi giá trị về kiểu số nguyên
- parseFloat() chuyển đổi giá trị về kiểu số thập phân
Number(true); // returns 1
Number(false); // returns 0
Number("10"); // returns 10
Number(" 10"); // returns 10
Number("10 "); // returns 10
Number(" 10 "); // returns 10
Number("10.33"); // returns 10.33
Number("10,33"); // returns NaN
Number("10 33"); // returns NaN
Number("John"); // returns NaN
parseInt("10"); // returns 10
parseInt("10.33"); // returns 10
parseInt("10 20 30"); // returns 10
parseInt("10 years"); // returns 10
parseInt("years 10"); // returns NaN
parseFloat("10"); // returns 10
parseFloat("10.33"); // returns 10.33
parseFloat("10 20 30"); // returns 10
parseFloat("10 years"); // returns 10
parseFloat("years 10"); // returns NaN
6. Chuỗi – String
Chuỗi có thể được chứa trong nháy đơn hoặc nháy kép. Vị trí đầu tiên của chuỗi là 0.
var carName1 = "Volvo XC60"; // Double quotes
var carName2 = 'Volvo XC60'; // Single quotes
7. Một số phương thức hay dùng
length trả về độ dài của chuỗi
var txt = 'Ben'
var sln = txt.length // 3
indexOf() trả về vị trí đầu tiên của từ khóa trong một chuỗi. Nếu không có sẽ trả về -1
var str = "Please locate where 'locate' occurs!"
var pos = str.indexOf('locate') // 7
Tách chuỗi
Có 3 phương thức tách chuỗi
slice(start, end): Tách từ vị trí start đến vị trí end – 1
var str = 'Apple, Banana, Kiwi'
var res = str.slice(7, 13) // Banana
//Nếu tham số là giá trị âm thì vị trí sẽ được đếm từ phía sau
str.slice(-12, -6) // Banana
//Nếu không có tham số thứ 2 thì coi như đếm đến cuối
str.slice(7) // Banana, Kiwi
str.slice(-12) // Banana, Kiwi
substring(start, end): Tương tự với slice nhưng không thể nhận giá trị âm
var str = 'Apple, Banana, Kiwi'
var res = str.substring(7, 13) // Banana
substr() tương tự slice() nhưng tham số thứ 2 là độ dài chuỗi
var str = 'Apple, Banana, Kiwi'
var res = str.substr(7, 6) // Banana
str.substr(7) // Banana, Kiwi
str.substr(-4) // Kiwi
replace(): Thay thế chuỗi
var str = 'Please visit Microsoft and Microsoft!'
var n1 = str.replace('Microsoft', 'W3Schools')
var n2 = str.replace(/Microsoft/g, "W3Schools");
console.log(n1) // Please visit W3Schools and Microsoft!
console.log(n2) // Please visit W3Schools and W3Schools!
Chuyển đổi sang chữ hoa hoặc chữ thường (upper and lower case)
var text1 = 'Hello World!'
var text2 = text1.toUpperCase() // HELLO WORLD!
var text3 = text1.toLowerCase() // hello world!
concat(): Nối chuỗi
var text1 = 'Hello'
var text2 = 'World'
var text3 = text1.concat(' ', text2) // Hello World
trim(): Xóa khoảng trắng 2 bên chuỗi
var str = ' Hello World! '
var newStr = str.trim() // Hello World!
charAt() hoặc []: Lấy ký tự từ một chuỗi
var str = 'HELLO WORLD'
str.charAt(0) // returns H
str[0] // returns H
str[0] = 'A' // Không bị lỗi nhưng đoạn code này không hoạt động
charCodeAt(): Lấy UTF-16 code tại vị trí bất kì trong chuỗi
var str = 'HELLO WORLD'
str.charCodeAt(0) // returns 72
split(): Chuyển chuỗi sang mảng. Tham số là chuỗi ngăn cách
const txt1 = 'a,b,c,d,e'
const array1 = txt1.split(',') // [ 'a', 'b', 'c', 'd', 'e' ]
// Nếu tham số là rỗng thì sẽ return về mảng từng ký tự
const txt2 = 'Hello'
const array2 = txt2.split('') // [ 'H', 'e', 'l', 'l', 'o' ]
8. Mảng – Array
// Mảng có thể chứa nhiều kiểu dữ liệu bên trong
const cars = [{ name: 'BMW', location: 'germany' }, 'Toyota', 24]
console.log(cars[1]) // Toyota
cars[0].name = 'Mercedes'
console.log(cars) // [ { name: 'Mercedes', location: 'germany' }, 'Toyota', 24 ]
Một số phương thức và thuộc tính hay dùng
length: return độ dài mảng
const num = [1, 2, 3, 4]
num.length // 4
Array.isArray() hoặc instanceof để nhận biết một biến có phải là mảng hay không
const fruits = ['Banana', 'Orange', 'Apple', 'Mango']
Array.isArray(fruits) // true
fruits instanceof Array // true
toString() hoặc join() để chuyển mảng sang chuỗi
const fruits = ['Banana', 'Orange', 'Apple', 'Mango']
const str1 = fruits.toString() // Banana,Orange,Apple,Mango
const str2 = fruits.join('-') // Banana-Orange-Apple-Mango
push(): thêm 1 phần từ vào cuối mảng, return lại chiều dài mảng mới
const fruits = ['Banana', 'Orange', 'Apple']
const x = fruits.push('Mango') // giá trị của x là 4
pop(): xóa phần tử cuối cùng của mảng, return lại phần tử vừa xóa
const fruits = ['Banana', 'Orange', 'Apple', 'Mango']
const x = fruits.pop() // giá trị của x là Mango
shift(): xóa phần tử đầu tiên của mảng, return lại phần tử vừa xóa
const fruits = ['Banana', 'Orange', 'Apple', 'Mango']
const x = fruits.shift() // giá trị của x là Banana
unshift(): thêm 1 phần tử vào đầu mảng, return lại chiều dài mảng mới
const fruits = ['Orange', 'Apple', 'Mango']
const x = fruits.unshift('Banana') // giá trị của x là 4
Lưu ý khi dùng delete, phần tử sẽ bị mất khỏi mảng nhưng để lại 1 khoảng trống. Khi truy cập đến khoảng trống này thì giá trị của nó là undefined
const fruits = ['Banana', 'Orange', 'Apple', 'Mango']
delete fruits[0]
console.log(fruits) // [ <1 empty item>, 'Orange', 'Apple', 'Mango' ]
console.log(fruits.length) // 4
splice(vị trí thêm, số lượng cần xóa, … phần tử thêm): Hàm splice dùng để thêm hoặc xóa nhiều phần tử trong 1 mảng. Return về mảng với những phần tử vừa được xóa
const fruits = ['Banana', 'Orange', 'Apple', 'Mango']
// Thêm vào vị trí số 2
const x = fruits.splice(2, 0, 'Lemon', 'Kiwi')
console.log(x) // [] vì không xóa phần tử nào mà chỉ thêm
console.log(fruits) // [ 'Banana', 'Orange', 'Lemon', 'Kiwi', 'Apple', 'Mango' ]
const fruits = ['Banana', 'Orange', 'Apple', 'Mango']
// Xóa 1 phần tử tại vị trí số 0
const x = fruits.splice(0, 1)
console.log(x) // [ 'Banana' ]
console.log(fruits) // [ 'Orange', 'Apple', 'Mango' ]
slice(vị trí bắt đầu, vị trí kết thúc): tách ra một mảng mới từ mảng cũ
const fruits = ['Banana', 'Orange', 'Apple', 'Mango']
// tách ra 1 mảng mới bắt đầu tại vị trí đầu tiên đến vị trí cuối
const newFruits = fruits.slice(1)
console.log(newFruits) // [ 'Orange', 'Apple', 'Mango' ]
console.log(fruits) // [ 'Banana', 'Orange', 'Apple', 'Mango' ]
// tách ra 1 mảng mới bắt đầu tại vị trí 1 đến 2 (3-1)
const newFruits2 = fruits.slice(1, 3)
console.log(newFruits2) //[ 'Orange', 'Apple' ]
concat(): Tạo mới một mảng bằng cách nối các mảng cũ
const myGirls = ['Cecilie', 'Lone']
const myBoys = ['Emil', 'Tobias', 'Linus']
const myChildren = myGirls.concat(myBoys) // [ 'Cecilie', 'Lone', 'Emil', 'Tobias', 'Linus' ]
spread operator : Phân rã mảng (object) thành từng phần tử nhỏ ( tưởng tượng [1,2,3] => 1,2,3)
const cars1 = [1, 2, 3]
const cars2 = [3, 4, 5]
// Nối mảng
const newCars = [...cars1, ...cars2] // [ 1, 2, 3, 3, 4, 5 ]
// Tạo thành 1 mảng mới
const cars3 = [...cars1] // [1, 2, 3]
console.log(cars1 !== cars3) // true
forEach(): Lặp qua từng phần tử trong mảng
tham số là một callback function với 3 đối số:
- giá trị phần tử
- index phần tử
- mảng đang thực hiện
const numbers = [1, 2, 3, 4, 5, 6, 7]
const newNumbers = []
numbers.forEach((value, index, array) => {
newNumbers.push(value)
})
console.log(newNumbers) // [1, 2, 3, 4, 5, 6, 7]
map(): Tạo một mảng mới bằng cách thực hiện tính toán trên mỗi phần tử. map() không thay đổi mảng cũ
const numbers = [1, 2, 3]
const newNumbers = numbers.map((value, index, array) => {
return value * 2
})
console.log(newNumbers) // [2, 4, 6]
filter(): Tạo một mảng mới với những phần tử thỏa điều kiện
const numbers = [1, 2, 3]
const newNumbers = numbers.filter((value, index, array) => {
return value >=2
})
console.log(newNumbers) // [2, 3]
find(): trả về phần tử thỏa điều kiện đầu tiên. Nếu không có sẽ return undefined
const numbers = [1, 2, 3]
const result = numbers.find((value, index, array) => {
return value >= 2
})
console.log(result) // 2
findIndex(): trả về index của phần tử thỏa điều kiện đầu tiên. Nếu không có sẽ return -1
const cars = ['BMW', 'Toyota', 'Hyundai']
const result = cars.findIndex((value, index, array) => {
return value === 'Toyota'
})
console.log(result) // 1
indexOf(): trả về index của phần tử trong mảng. Nếu không có sẽ return -1
const cars = ['BMW', 'Toyota', 'Hyundai']
const index = cars.indexOf('Toyota')
console.log(index) // 1
every(): Nếu mọi phần tử thỏa điều kiện sẽ return true, còn không sẽ return false
const numbers = [1, 2, 3]
const check = numbers.every((value, index, array) => {
return value > 2
})
console.log(check) // false
some(): Nếu có một phần tử thỏa điều kiện sẽ return true, còn không sẽ return false
const numbers = [1, 2, 3]
const check = numbers.some((value, index, array) => {
return value > 2
})
console.log(check) // true
includes(): Kiểm tra một phần tử có trong mảng hay không. return true/false
const numbers = [1, 2, 3, 4, 5]
const check = numbers.includes(5) // true
Thường thì các method với tring, array không thay đổi giá trị gốc. Ngoại trừ: pop, push, shift, unshift, delete
9. Object
- entry của object là cặp key, value tương ứng. entry còn được coi như là property (thuộc tính) của object
- key thì luôn luôn là một string hoặc number
- value có thể là bất cứ giá trị nào của Javascript, kể cả function
- method (phương thức) là những thuộc tính mà value của nó là function
const user = {
name: 'Ben',
age: 28,
greet() {
console.log('Hello, My name is ' + this.name)
},
}
user.greet() // Hello, My name is Ben
prototype object
Prototype là cơ chế mà giúp các Javascript object thừa kế các tính năng từ các object khác.
Theo như các bài trước ta biết rằng JS có 2 kiểu data là kiểu nguyên thủy (numer, string, boolean…) và object. Nhưng nếu hiểu kĩ hơn thì ẩn sâu bên trong Javascript, ngoại trừ undefined thì toàn bộ các kiểu dữ liệu còn lại đều là object. Các kiểu string, number, boolean lần lượt là object dạng String, Number, Boolean. Mảng là object dạng Array, hàm là object dạng Function.
var str = 'abc'; // str là string, cha nó là String.prototype
// nhân đôi chuỗi đưa vào
String.prototype.duplicate = function() { return this + this; }
console.log(str.duplicate()); // Tìm thấy hàm duplicate trong prototype
// object literal
var person = {
firstName: 'Anh',
lastName: 'Ben',
showName: function() {
console.log(this.firstName + ' ' + this.lastName)
},
} // object này có prototype là Object.prototype
// Constructor Function
function Person(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
this.showName = function() {
console.log(this.firstName + ' ' + this.lastName)
}
}
var otherPerson = new Person('Anh', 'Ben') // object này có prototype là Person.prototype
// Prototype mới: Person.prototype được tạo ra
// Person.prototype kế thừa Object.prototype
Thêm một phương thức vào object được tạo từ một constructor function
// STEP 0: tạo ra 1 hàm
function Student(name, age) {
this.name = name
this.age = age
}
// STEP 1: tạo 1 đối tượng s1 bằng toán tử new
const s1 = new Student('Nguyen Vu Hoang', 28)
// STEP 2: thêm một hàm sayHello() cho Student như sau:
Student.sayHello = function() {
console.log('Hello')
}
// STEP 3: thêm 1 hàm showName() cho prototype của Student như sau:
Student.prototype.showName = function() {
console.log('My name: ', this.name)
}
// STEP 4: Gọi lần lượt hai hàm trên từ s1:
s1.sayHello() // Lỗi, vì s1 ko có hàm sayHello, hàm này chỉ thuộc Student thôi.
s1.showName() // In ra: 'My name: Nguyen Vu Hoang'
// Cuối cùng, thử câu sau:
Student.sayHello() // In ra 'Hello'
Có thể sửa prototype của một function thông qua object (đối tượng) được tạo từ function đó
s1.__proto__.study = function() {
console.log(`Tôi là ${this.name}, Tôi đang học bài.`)
}
// Thử tạo s2 và gọi s2.study()
const s2 = new Student('Badder Cuder', 30)
s2.study() // In ra: 'Tôi là Badder Cuder, Tôi đang học bài.'
Một số điều thú vị về __proto__.
- Có thể coi prototype là đối tượng tạo ra __proto__
const user = {
name: 'Ben',
age: 28,
greet() {
console.log('Hello, My name is ' + this.name)
},
__proto__: {
describe() {
console.log('I am' + this.age + ' years old')
},
},
}
user.greet() // Hello, My name is Ben
user.describe() // I am 28 years old
Một số phương thức thường thao tác với object
Đọc – thêm – sửa – xóa thuộc tính object
const person = {
name: 'Ben',
}
// đọc thuộc tính name
person.name
// thêm thuộc tính vào person
person.ability = ['dance', 'sing']
// sửa thuộc tính name
person.name = 'Alan'
// xóa thuộc tính name
delete person.name
Object.assign(): dùng để merge object/p>
const person = {
name: 'Ben',
ability: ['programing'],
}
const person2 = Object.assign(person, { ability: ['dance', 'sing'] })
console.log(person2) // { name: 'Ben', ability: [ 'dance', 'sing' ] }
spread operator: dùng để shallow copy hoặc merge object
const person = {
name: 'Ben',
ability: ['programing'],
}
const person2 = { ...person, ability: ['dance', 'sing'] }
console.log(person2) // { name: 'Ben', ability: [ 'dance', 'sing' ] }
Object.keys(): trả về mảng các key của object
const person = {
name: { firstName: 'Anh', lastName: 'Ben' },
age: 28,
}
console.log(Object.keys(person)) // [ 'name', 'age' ]
Object.values(): trả về mảng các value của object
const person = {
name: { firstName: 'Anh', lastName: 'Ben' },
age: 28,
}
console.log(Object.values(person)) // [ { firstName: 'Anh', lastName: 'Ben' }, 28 ]
10. Lớp – Class
Class là tính năng của ES6 sinh ra để giải quyết cú pháp kế thừa prototype phức tạp bằng cách dùng class và extends. Ẩn dưới class vẫn là prototype, lâp trình với class giống như lập trình bậc cao, còn prototype là bậc thấp vậy
class Human {
constructor(name) {
this.name = name
}
sing() {
console.log(`${this.name} đang hát...`)
}
}
class Student extends Human {
constructor(name, grade) {
// Khởi tạo Human bên trong Student
// truyền name vào constuctor của Human
super(name)
this.grade = grade
}
study() {
console.log(`${this.name} có ${this.grade} điểm`)
}
}
const duoc = new Student('Nguyen Vu Hoang', 100)
// Student kế thừa hàm sing() từ Human, nên duoc có thể gọi
duoc.sing()
// duoc gọi hàm study(), bên trong study sử dụng "this.name",
duoc.study()
Khi bạn dùng extends
thì nên khai báo super()
ngay dưới constructor()
, nếu không thì khi tạo đối tượng mới từ class sẽ bị lỗi!
Khai báo thuộc tính tĩnh (static property chưa phổ biến trên nhiều trình duyệt nên mình không đề cập) hoặc phương thức tĩnh (static method) với static
- Lưu ý static method chỉ được gọi ở class, không thể gọi được ở đối tượng được tạo từ class
class Human {
constructor(name) {
this.name = name
}
static sing() {
console.log(`${this.name} đang hát...`)
}
}
Human.sing() // Human đang hát...
(new Human('Ben')).sing() // Lỗi Human.sing(...) is not a function
get và set
class Human {
constructor(name) {
this._name = name
}
get name() {
return this._name.toUpperCase()
}
set name(newName) {
this._name = newName
}
}
const duoc = new Human('Duoc')
duoc.name = 'Alan'
console.log(duoc.name) // ALAN