js-OOP: Xây dựng class mẫu với javascript – Part 1

js-OOP: Xây dựng class mẫu với javascript – Part 1

Trong javascript, chủ yếu lập trình viên sử dụng các class, object mà được browser cung cấp sẵn. Bên cạnh đó, ta hoàn toàn có thể xây dựng được các class trên javascript, mặc dù không được đầy đủ các tính chất như trong lập trình hướng đối tượng.
Trong bài viết này tôi sẽ xây dựng một mẫu đơn giản cho phép ta cài đặt một class có khả năng che dấu các biến và các hàm (private property và private method), cài đặt các biến và hàm dạng public static, cài đặt hàm khởi tạo.

Kỹ thuật che dấu

Cũng giống như các ngôn ngữ lập trình khác, khi một biến được khai báo bên trong block thì bên ngoài block đó sẽ không truy cập được:

{
    var x = 1;
    // ...
    x = 2; // truy cập hợp lệ 
}
x  = 3; // truy cập không hợp lệ, phát sinh lỗi

Block ở đây có thể là một khối lệnh được định nghĩa bên trong cặp ngoặc nhọn {…} hoặc bên trong thân một hàm function (){…}

Class object trong javascript

Một object trong javascript được khai báo đơn giản như sau:

var obj = new Object();
// hoặc
var obj = {};

Để định nghĩa biến thành viên ta làm như sau:

var obj = new Object();
obj.x = 10;
obj.y = "suco";
// hoặc
var obj = {x: 10, y: "suco"};

Trong javascript, có một kiểu dữ liệu đặc biệt là function, một biến có kiểu là function thì có thể thực hiện việc gọi hàm thông qua biến đó. Dựa vào tính chất này, ta định nghĩa hàm thành viên cho lớp:

var obj = new Object();
obj.sayHello = function (name) {alert(name);};
// hoặc
var obj = {sayHello: function (name) {alert(name);}};

// thực hiện gọi hàm
obj.sayHello("suco");

Kỹ thuật công khai (public) các hàm và biến thành viên

Đối với các biến thành viên, hàm thành viên khi đã được khai báo gắn vào class thì đều là public và đều có thể được truy cập từ bên ngoài.

Xây dựng hàm khởi tạo đơn giản trong javascript

Hàm khởi tạo thực chất cũng là một hàm thông thường nhưng nó được cấp phát bộ nhớ để tạo ra một thể hiện bằng cách sử dụng từ khóa new. Khi có bộ nhớ được cấp phát, ta có thể sử dụng tham chiếu this dành các hàm thành viên truy cập đến thể hiện vừa được tạo.

Ví dụ một hàm khởi tạo đơn giản:

function A(p){
	alert("Hàm khởi tạo của lớp A với tham số p = " + p);
}
var a = new A(1);
alert(typeof(a));

Ta thu được 2 thông báo: “Hàm khởi tạo của lớp A với tham số p = 1″ và “object”

Sử dụng this

Từ khóa this chứa tham chiếu đến thể hiện hiện tại của lớp, nó có ý nghĩa tương tự như từ khóa this trong các ngôn ngữ lập trình hướng đối tượng dòng C như C++, C#, Java…
Tôi sẽ định nghĩa thuộc tính name và phương thức alertName cho lớp A bên trong chính lớp A thay vì định nghĩa rồi gán vào thể hiện như trong phần “Class, object trong javascript” ở bên trên:

function A(p){
	this.name = p;
	this.alertName = function(){alert(this.x);}
}
var a = new A("suco");
a.alertName();

Mẫu xây dựng class đơn giản trong javascript

Nhìn vào cách xây dựng class ở trên, kết hợp cùng cách che dấu giữ liệu, tôi thường xây dựng class theo mẫu như sau:

function TemplateClass(param1, param2){
	var _this = this;

	// định nghĩa các biến private
	var private1 = 1;
	var private2 = "giá trị";
	var privateProperty;

	// định nghĩa các hàm private
	var privateMethod1 = function(){
		// thân hàm: có thể sử dụng các biến, các hàm public và private, 
		// các biến, hàm public truy cập qua _this
	}
	
	function privateMethod2(x){
		// thân hàm: có thể sử dụng các biến, các hàm public và private, 
		// các biến, hàm public truy cập qua _this
	}

	// định nghĩa public variable
	this.publicVariable = 0;

	// định nghĩa các thuộc tính (cài đặt setter và getter)
	this.publicProperty = function(value){
            if (typeof (value) === 'undefined') return privateProperty;
            // thực hiện validate value nếu cần
            privateProperty = value;
	}

	// định nghĩa các hàm public
	this.publicMethod = function(params) {
		// thân hàm: có thể sử dụng các biến, các hàm public và private, 
		// các biến, hàm public truy cập qua this
	}

	(function(){
		// thân hàm khởi tạo: có thể sử dụng các biến, các hàm public và private, các tham số khởi tạo
		// các biến, hàm public truy cập qua _this
	})();
}

Để dễ hiểu, tôi sẽ định nghĩa class Rectangular (hình hộp chữ nhật) với 3 thuộc tính chiều dài (width), chiều cao (high) và độ sâu (deep), một phương thức private là isPositive cho biết một số có phải là dương hay không, một phương thức public trả về dung tích của khối hộp getVolume.

function Rectangular(width, high, deep) {
	var _this = this;
	/// Định nghĩa Private Property
	var _width, _high, _deep;

	/// Định nghĩa Private Method
	function isPositive(x) {
		return x > 0;
	}

	/// Định nghĩa Public Property
	this.width = function (value) {
		if (typeof (value) === 'undefined') return _width;
		if (!isPositive(value)) throw "Value phải là số dương";
		_width = value;
	};
	this.high = function (value) {
		if (typeof (value) === 'undefined') return _high;
		if (!isPositive(value)) throw "Value phải là số dương";
		_high = value;
	};
	this.deep = function (value) {
		if (typeof (value) === 'undefined') return _deep;
		if (!isPositive(value)) throw "Value phải là số dương";
		_deep = value;
	};

	/// Định nghĩa Public Method
	this.getVolume = function () {
		return _this.width() * _this.high() * _this.deep();
	};

	/// Định nghĩa Public CONSTRUCTION
	(function () {
		_this.width(width);
		_this.high(high);
		_this.deep(deep);
	})();
};

Sử dụng class trên:

var rec = new Rectangular(1, 2, 3);
alert(rec.getVolume());
rec.width(4);
alert(rec.getVolume());

Trên đây tôi đã trình bày cách xây dựng một class theo mẫu, các bạn có thể sử dụng mẫu trên để cài đặt cho các lớp mà các bạn đang cần xây dựng.
Trong các bài viết sau, tôi sẽ giới thiệu cách giả lập một namespace trong javascript.

Khi trích dẫn bài viết từ tek.eten.vn, xin vui lòng ghi rõ nguồn. Chúng tôi sẽ rất cảm ơn bạn!