Hướng dẫn javascript static method this - javascript static method this

Trong bài này chúng ta sẽ tìm hiểu cách sử dụng từ khóa static trong javascript, qua đó sẽ giúp bạn hiểu được cách sử dụng static để tạo ra các thuộc tính và phương thức tĩnh.

Hướng dẫn javascript static method this - javascript static method this

Hướng dẫn javascript static method this - javascript static method this

Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.freetuts.net, không được copy dưới mọi hình thức.

Static xuất hiện trong các ngôn ngữ lập trình hướng đối tượng là quá bình thường. Nhưng với javascript thì khác, static chỉ xuất hiện kể từ phiên bản ES6 - 2015. Vì vậy, với những trình duyệt cũ thì sẽ không hoạt động.

1. Static trong javascript là gì?

Static là một từ khóa giúp ta khai báo những phương thức tĩnh hoặc thuộc tính tĩnh trong các class của javascript. Khi được khai báo static thì phương thức / thuộc tính đó có thể được gọi đến mà không cần phải sử dụng từ khóa new để khởi tạo đối tượng.phương thức tĩnh hoặc thuộc tính tĩnh trong các class của javascript. Khi được khai báo static thì phương thức / thuộc tính đó có thể được gọi đến mà không cần phải sử dụng từ khóa new để khởi tạo đối tượng.

Cú pháp như sau: Ta chỉ cần đặt từ khóa static đằng trước phương thức / thuộc tính là được.: Ta chỉ cần đặt từ khóa static đằng trước phương thức / thuộc tính là được.

Bài viết này được đăng tại [free tuts .net]

class className {    
    // Static property
    static name = "";
    
    // Static method
    static functionName(){
        
    }
}

Static method trong javascript

Static method là những phương thức có từ khóa static phía trước. Các phương thức như vậy được gọi là static method.static method.

Ví dụ

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true

Điều này giống như bạn tạo một phương thức từ bên ngoài lớp như sau:

// Khai báo lớp
class User { }

// Thêm một static method
User.staticMethod = function() {
  alert(this === User);
};

User.staticMethod(); // true

Qua 2 ví dụ này thì ta thấy từ khóa

// Khai báo lớp
class User { }

// Thêm một static method
User.staticMethod = function() {
  alert(this === User);
};

User.staticMethod(); // true
0 bên trong static method chính là class của nó.

Tuy nhiên, ta không thể sử dụng từ khóa this để gọi đến một phương thức không phải là static.this để gọi đến một phương thức không phải là static.

class User {
    sayHi() {
        console.log("Xin chào");
    }
    static staticMethod() {
        // Sai, vì sayHi không phải là static
        this.sayHi();
    }
}
// Không cần phải khởi tạo
User.staticMethod(); // true

Static properties trong javascript

Static properties hay còn gọi là thuộc tính tĩnh, là những thuộc tính có đặt từ khóa static phía trước.

Những thuộc tính như vậy ta có thể truy cập đến mà không cần phải khởi tạo đối tượng.

class Article {
  static publisher = "Cường Nguyễn";
}

alert( Article.publisher ); // Cường Nguyễn

2. Sử dụng this để truy cập thuộc tính static

Nếu bạn sử dụng

// Khai báo lớp
class User { }

// Thêm một static method
User.staticMethod = function() {
  alert(this === User);
};

User.staticMethod(); // true
0 để truy cập đến một thuộc tính static thì nó sẽ trả về undefined. Bởi vì một thuộc tính static sẽ không nằm trong danh sách thuộc tính của class, mà nó được lưu trữ trong constructor của class.undefined. Bởi vì một thuộc tính static sẽ không nằm trong danh sách thuộc tính của class, mà nó được lưu trữ trong constructor của class.

class Article {
    static publisher = "Cường Nguyễn"
    show() {
        // Xuất ra undefined
        alert(this.publisher);
    }
}

let a = new Article();
a.show(); // kết quả là undefined

Thử sử dụng lệnh console.log để xem trong biến a có gì nhé.

Như bạn thấy ở trong hình, thuộc tính static publisher đã được lưu trữ trong constructor. Vì vậy, nếu bạn muốn sử dụng

// Khai báo lớp
class User { }

// Thêm một static method
User.staticMethod = function() {
  alert(this === User);
};

User.staticMethod(); // true
0 để truy cập đến nó thì phải sử dụng cú pháp
// Khai báo lớp
class User { }

// Thêm một static method
User.staticMethod = function() {
  alert(this === User);
};

User.staticMethod(); // true
3:

class Article {
    static publisher = "Cường Nguyễn"
    show() {
        alert(this.constructor.publisher);
    }
}

let a = new Article();
a.show(); // Cường Nguyễn

3. Thuộc tính static có giá trị duy nhất

Thuộc tính / phương thức static trong javascript là duy nhất nhé các bạn. Vì nó được lưu trữ trong constructor của class, mà dữ liệu trong constructor là duy nhất, nghĩa là những thay đổi bên trong constructor là ảnh hưởng đến đối tượng chứ không phải instance.

Đọc tới đây chắc nhiều bạn không hiểu instance là gì, thì mình xin giải thích như sau:

Ví dụ mình có lớp A, và mình tạo 2 biến như sau:A, và mình tạo 2 biến như sau:

class A{
    // code
}

let instance1 = new A();
let instance2 = new A();

Hai biến instance1 và instance2 ta gọi là các thể hiện (instance) của đối tượng A.

Quay lại vấn đề chính. Giả sử mình có class Article như sau:

class Article {
    static publisher = "Cường Nguyễn"
    change(new_value){
        this.constructor.publisher = new_value;
    }
    show() {
        console.log(this.constructor.publisher);
    }
}

Trong đó, hàm

// Khai báo lớp
class User { }

// Thêm một static method
User.staticMethod = function() {
  alert(this === User);
};

User.staticMethod(); // true
4 mình tạo ra với mục đích thay đổi dữ liệu cho thuộc tính
// Khai báo lớp
class User { }

// Thêm một static method
User.staticMethod = function() {
  alert(this === User);
};

User.staticMethod(); // true
5.

Bây giờ mình chạy đoạn code dưới đây:

let a = new Article();
a.show(); // Cường Nguyễn

let b = new Article();
b.change('Nguyễn Văn Cường');
b.show(); // Nguyễn Văn Cường

a.show(); // Nguyễn Văn Cường
console.log(Article.publisher); // Nguyễn Văn Cường     

Như bạn thấy,

  • Ban đầu a.show() sẽ in ra giá trị là Cường Nguyễn.
  • Sau khi chạy hàm
    // Khai báo lớp
    class User { }
    
    // Thêm một static method
    User.staticMethod = function() {
      alert(this === User);
    };
    
    User.staticMethod(); // true
    6 thì giá trị của publisher đã thay đổi
  • Tiếp tục chạy
    // Khai báo lớp
    class User { }
    
    // Thêm một static method
    User.staticMethod = function() {
      alert(this === User);
    };
    
    User.staticMethod(); // true
    7 và
    // Khai báo lớp
    class User { }
    
    // Thêm một static method
    User.staticMethod = function() {
      alert(this === User);
    };
    
    User.staticMethod(); // true
    8 thì đều cho ra kết quả giống nhau, và đó là giá trị mới thay đổi.

Điều này chứng tỏ thuộc tính publisher có giá trị duy nhất, bởi nó là dữ liệu của class chứ không phải trên instance.

4. Static trong kế thừa thuộc tính và phương thức

Một điều khá thú vị nữa, đó là nếu một thuộc tính là static thì trong kế thừa sẽ như thế nào? Để hiểu vấn đề này thì hơi hại não một chút, nên các bạn cần tập trung để xem những giải thích của mình nhé.

Đầu tiên bạn phải hiểu dữ liệu

// Khai báo lớp
class User { }

// Thêm một static method
User.staticMethod = function() {
  alert(this === User);
};

User.staticMethod(); // true
9 của một instance.

Khi bạn tạo một instance thì instance đó sẽ có một thuộc tính tên là

class User {
    sayHi() {
        console.log("Xin chào");
    }
    static staticMethod() {
        // Sai, vì sayHi không phải là static
        this.sayHi();
    }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
0. Trong
class User {
    sayHi() {
        console.log("Xin chào");
    }
    static staticMethod() {
        // Sai, vì sayHi không phải là static
        this.sayHi();
    }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
0 sẽ có một thuộc tính tên là
class User {
    sayHi() {
        console.log("Xin chào");
    }
    static staticMethod() {
        // Sai, vì sayHi không phải là static
        this.sayHi();
    }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
2. Đây chính là thông tin của class dùng để tạo ra biến instance đó.

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
0

Kêt quả trên cửa sổ console như sau:

Mình thử dùng phép toán so sánh thì kết quả là true:true:

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
1

Bây giờ mình sẽ cho class Post kế thừa một class khác, sau đó dùng console.log để xem:Post kế thừa một class khác, sau đó dùng console.log để xem:

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
2

Kết quả:

Như vậy class Article sẽ nằm trong hai vị trí:

  • Thứ nhất là
    class User {
        sayHi() {
            console.log("Xin chào");
        }
        static staticMethod() {
            // Sai, vì sayHi không phải là static
            this.sayHi();
        }
    }
    // Không cần phải khởi tạo
    User.staticMethod(); // true
    3 của Post
  • Thứ hai là trong
    class User {
        sayHi() {
            console.log("Xin chào");
        }
        static staticMethod() {
            // Sai, vì sayHi không phải là static
            this.sayHi();
        }
    }
    // Không cần phải khởi tạo
    User.staticMethod(); // true
    4 của Post

Ta thử dùng phép so sánh xem có chuẩn không nhé.

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
3

Cấu trúc dữ liệu của các đối tượng trong javascript quả là phức tạp phải không các bạn? Mục đích mình giải thích ở trên là giúp các bạn hiểu được một class kế thừa thì nó có cấu trúc như thế nào.

Bây giờ ta sẽ đi vào vấn đề chính nhé. Vẫn tiếp tục lấy hai class dưới đây làm ví dụ:

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
4

Bây giờ thử in thuộc tính

class User {
    sayHi() {
        console.log("Xin chào");
    }
    static staticMethod() {
        // Sai, vì sayHi không phải là static
        this.sayHi();
    }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
5 xem giá trị thế nào:

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
5

Cả hai đều cho một kết quả. Bây giờ ta thử thay đổi giá trị của

class User {
    sayHi() {
        console.log("Xin chào");
    }
    static staticMethod() {
        // Sai, vì sayHi không phải là static
        this.sayHi();
    }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
5.

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
6

Trường hợp này đã xuất hiện sự sai lệch. Nếu lớp con thay đổi giá trị static của lớp cha thì nó chỉ thay đổi cho lớp con mà thôi.

Bây giờ ta thử tạo mới một instance, sau đó log ra xem có gì nhé.

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
7

Các bạn thấy có sự sai lệch rồi phải không? Có vẻ như do mình sử dụng phép gán nên javascript sẽ tạo ra một thuộc tính static mới trên lớp Post. Vì vậy khi truy cập thì javascript vẫn ưu tiên lấy ở lớp Post.

Bây giờ ta thử hoán đổi hai class xem thế nào.

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
8

Kết quả là dữ liệu ở cả hai class đều thay đổi.

Ta thử chạy lệnh dưới đây để xem điêu gì đã xảy ra nhé.

class User {
  static staticMethod() {
    alert(this === User);
  }
}
// Không cần phải khởi tạo
User.staticMethod(); // true
9

Mọi thứ suôn sẻ, trong lớp Post không có thuộc tính publisher, nên khi gọi đến thuộc tính này thì cả hai class đều lấy chung một thuộc tính ở lớp Article.

Lời kết: Như vậy là mình đã hướng dẫn xong cách sử dụng static trong Javascript. Đây là một kiến thức khá quan trọng, nó giúp bạn hiểu được khái niệm static là gì, khi nào nên sử dụng static, và cách sử dụng static trong kế thừa. Hẹn gặp lại các bạn ở bài tiếp theo.: Như vậy là mình đã hướng dẫn xong cách sử dụng static trong Javascript. Đây là một kiến thức khá quan trọng, nó giúp bạn hiểu được khái niệm static là gì, khi nào nên sử dụng static, và cách sử dụng static trong kế thừa. Hẹn gặp lại các bạn ở bài tiếp theo.