تعریف ویژگی ها (Properties) در جاوا اسکریپت

28 11 2008

یکی از امکانات نسخه های جدید JavaScript پشتیبانی از ویژگی ها (Property) هست. اگر با سایر زبان های برنامه نویسی آشنایی داشته باشید، مطمئنن می دانید که ویزگی ها یکی از بخش های جدایی ناپذیر زبانهای برنامه نویسی OOP هستند.

ویژگی ها این امکان را فراهم می کنند که بر روی مقادیر متغیرهای خود کنترل داشته باشید و حق دسترسی برای آنها جهت ویرایش تعیین کنید. همچنین می توان داده های وارده را فیلتر کرده تا فقط محدوده و داده های مورد نظر اعمال شوند.

با این مقدمه می خواهم چند روش تعریف ویژگی ها در جاوا اسکریپت مطرح کنم.

تعریف اول:

جاوا اسکریپت زبان بسیار ساده ای است. ابجکت ها (یا اشیا) در جاوا اسکریپت چیزی بیش از مجموعه ای از کلید ها و مقادیر نیستند. به این معنی که برای دسترسی به عضوی از یک شیئ می توانید همانند یک آرایه با آن رفتار کنید.

برای مثال برای افزودن یک عضو به یک شیئ به مثال زیر توجه کنید:

var thing = new Object();
thing[ “prop1” ] = “Hello”;

در این مثال ما عضو جدیدی به نام prop1 را به thing اضافه کردیم. مقدار prop1 برابر Hello خواهد بود. روش دیگری هم برای افزودن عضو به شیئ مورد وجود دارد. به مثال زیر توجه کنید:

var thing = new Object();
thing.prop1 = “Hello”;

روش دیگر برای معرفی اشیا استفاده از لیتراتهای ابچکت هست که نتیجه ای دقیقا مانند دو مثال قبلی دارد:

var thing = {prop1 : “Hello”};

استفاده از مقدار prop1 بسیار ساده است می توان همانند یک آرایه یا یک ویژگی از آن استفاده کرد:

var thing = new Object();
thing.prop1 = “Hello”;
alert( thing[“prop1”] );
thing.prop1 = “Hello Again!”;
alert( thing.prop1 );

روش دوم:

روشی که در بالا توضیح دادم خیلی ساده و کاربردی است ولی تنها محدودیتی که دارد این است که امکان کنترل بر داده هایی که قبول می کند و یا مقداری که باید برگرداند وجود ندارد.

برای رفع این مشکل شرکت Mozilla راه حلی را ارائه کرده است که به مرور سایر مرورگر ها نیز از آن پشتیبانی می کنند.

این روش چیزی جز کلمات کلیدی get و set نیست.

var thing =  {
_price: 0,
get price() { return this._price; },
set price(value)
{
	if (value < 0)
	throw "price must be greater than zero";
	this._price = value;
}
};

در این مثال شیئ با نام thing تعریف شده است. این شیئ دارای یک متغیر با نام price_ و ویژگی price هست که با استفاده از یک متد get و یک متد set تعریف شده است.

به طور ساده تر زمانی که می خواهید مقداری را از ویزگی price بخوانید تابع معرفی شده در مقابل get فراخوانی خواهد شد و همچنین، هنگام مقدار دهی به price تابع معرفی شده در مقابل set فراخوانی خواهد شد.

همانطور که می بینید ویزگی price در هنگام عمل set مقدار ورودی را بررسی می کند و اگر کوچکتر از صفر باشد خطایی را تولید خواهد کرد.

نمونه استفاده از کد بالا:

// مقدار دهی
thing.price = 5;
// نمایش مقدار
alert( thing.price );
// مقدار نامعتبر و تولید خطا
thing.price = -10;

متاسفانه از این روش مرورگر های کمی پشتیبانی می کنند و در حال حاظر مرورگرهای Firefox و Safari 3 و Opera 9.5 از آن پشتیبانی می کنند.

روش سوم:

این روش را مرورگر Firefox برای استفاده در خودش طراحی کرده و در سایر مرورگرها کار نخواهد کرد. روش بسیار جالبی است و ساده تر از روش قبلی می باشد.

var thing =
{
_price: 0
};
thing.__defineGetter__("price", function(){ return this._price; });
thing.__defineSetter__("price", function(value)
{
	if (value < 0)
		throw "price must be greater than 0";
	this._price = value;
}
);

در این مثال ابتدا شیئ thingتعرفی می شود. سپس با استفاده از تابع __defineGetter__ متد get با برای ویژگی price تعریف می شود. این تابع دو ورودی دارد که اولی نام ویژگی مورد نظر است و دومی رفرنسی به تابع مورد نظر برای get. البته در این مثال تابع در همان جا تعریف شده است.

تابع __defineSetter__ همانند __defineGetter__ عمل می کند و فقط برای اضافه کردن تعریف set به ویژگی مورد نظر مورد استفاده است. در این مثال تابع مربوط به set در همان خط تعریف شده و مقدار ورودی را برای مقادیر کمتر از صفر کنترل می کند.

همانند مثال قبلی این مثال نیز کار خواهد کرد:

// مقدار دهی
thing.price = 5;
// نمایش مقدار
alert( thing.price );
// مقدار نامعتبر و تولید خطا
thing.price = -10;

روش چهارم:

در این روشی که می خوام معرفی کنم، واقعا ویژگی ها را پیاده سازی نمی کند ولی مانند یک ویژگی عمل می کنه و می تونه در کار شما مفید واقع بشه. در این روش در حقیقت ما دو تابع جداگانه برای خواندن و نوشتن در متغیر تعریف می کنیم و کارهای مورد نظر را در داخل آنها انجام می دهیم.

function thing()
{
	var _price = 0;
	this.getPrice = function(){
		return _price;
	};
	this.setPrice = function(val){
		if (val < 0)
			throw "price must be greater than 0";
		_price = val;
	};
}

در این مثال شیئ thing به عنوان یک تابع تعریف شده است که می توان از روی متغیر و اشیا دیگری هم ساخت. در داخل این تابع دو تابع getPrice برای خواندن و setPrice برای نوشتن در متغیر _price تعریف شده است.

// ایجاد نمونه جدید از تابع تعریف شده
var product= new thing();
// دسترسی متقیم به متغیر داخلی
alert(product._price);
//مقدار دهی با استفاده از تابع
product.setPrice(2);
// دسترسی به مقدار با استفاده از تابع مربوطه
alert( product.getPrice() );
// مقدار با یک مقدار نامعتبر و دریافت خطا
product.setPrice( -4 );

با این اوصاف مشاهده می کنید که javascript روز به روز قوی تر می شود، مخصوصا که Web 2 بسیار به javascript وابسته هستند.

موفق باشید

منابع:

http://weblogs.asp.net/stephenwalther/archive/2008/02/29/creating-javascript-properties-in-asp-net-ajax.aspx
http://ejohn.org/blog/javascript-getters-and-setters/
http://ajaxian.com/archives/getters-and-setters-in-javascript


کارها

Information

7 responses

30 11 2008
Behrouz

بسیار عالی بود ممنون

20 12 2008
PMan

ممنون, مطلب جالب و کاربردی ای بود

29 01 2009
SyntaxHighlighter با طعم JQuery « نوشته های یک برنامه نویس

[…] تعریف ویژگی ها (Properties) در جاوا اسکریپت […]

7 02 2009
مهراد

این روش از نظر encapsulation مشکل داره
نباید به متغیر داخلی ، دسترسی مستقیم داشت و باید private باشد.
عملآ هنوز هم قادر به مقدار دهی اشتباه هستیم.
جالب اینجاس که قبل از مقدار دهی اشتباه این روش کار میکند
یعنی اگر مقدار thing._price را با alert فراخوانی کنیم مقدار undefined میدهد یعنی دسترسی به price نداریم
حال اگر thing._price=2 را انجام دهیم و دوباره مقدار thing._price را با alert فراخوانی کنیم ، مقدار 2 را میدهد ، این یعنی price حالت private بودن خود را از دست میدهد

در هر صورت ممنون از لطفتون برای این پست
قسمت آخر خط 01 که code نوشتید var thing=new thing باید به صورت
var product=new thing باشد تا باقی کد صحیح باشد چون مقدار product تعریف نشده

🙂 منبع

7 02 2009
Salar

@مهراد: نه خیر! شما به متغیر داخلی دسترسی پیدا نمی کنید. در حقیقیت این از خاصیت های javascript هست که می توان به ویژگیهایی که از قبل وجود ندارند مقداردهی کرد. برای مثال document.myWidth=90

در موردی هم گفتید در حقیقیت شما دارید یک آرایه از اشیا خارجی به شی را دستکاری می کنید که در متغیر داخلی هم نام هیچ تاثیری ندارد و شما رو به اشتباه انداخته است.

این رو امتحان کنید:
var product = new thing();
product.setPrice(2);
alert("product._price:"+product._price);
alert("product.getPrice():" + product.getPrice());
product._price = 6;
alert("product._price:" + product._price);
alert("product.getPrice():" + product.getPrice());

کد آخری رو هم به حساب اشتباه تایپی بذارید😉

9 02 2009
مهراد

کاملآ درسته🙂 کلی چیز ازتون یاد گرفتیم ، ممنون

31 08 2009

پاسخی بگذارید

در پایین مشخصات خود را پر کنید یا برای ورود روی شمایل‌ها کلیک نمایید:

نشان‌وارهٔ وردپرس.کام

شما در حال بیان دیدگاه با حساب کاربری WordPress.com خود هستید. بیرون رفتن / تغییر دادن )

تصویر توییتر

شما در حال بیان دیدگاه با حساب کاربری Twitter خود هستید. بیرون رفتن / تغییر دادن )

عکس فیسبوک

شما در حال بیان دیدگاه با حساب کاربری Facebook خود هستید. بیرون رفتن / تغییر دادن )

عکس گوگل+

شما در حال بیان دیدگاه با حساب کاربری Google+ خود هستید. بیرون رفتن / تغییر دادن )

درحال اتصال به %s




%d وب‌نوشت‌نویس این را دوست دارند: