首頁 web前端 js教程 JavaScript物件導向教程

JavaScript物件導向教程

Dec 20, 2016 pm 03:23 PM
javascript 物件導向

Javascript是一個類別C的語言,他的物件導向的東西相對於C++/Java比較奇怪,但是其的確相當的強大。這兩天有個前同事總是問我Javascript物件導向的東西,所以,索性寫篇文章讓他看去吧,這裡這篇文章主要想從一個整體的角度來說明一下Javascript的物件導向的程式設計。轉自酷殼的一篇文章,寫的很好·······

另,這篇文章主要基於 ECMAScript 5, 旨在介紹新技術。關於相容性的東西,請看最後一節。

  初探

我們知道Javascript中的變數定義基本上如下:

var name = 'Chen Hao';;

var email = 'haoel(@)hotmail.com';

var email = 'haoel(@)hotmail.com';

var email = /coolshell.cn';

如果要用物件來寫的話,就是下面這個樣子:

var chenhao = {

name :'Chen Hao',

email : 'haoel(@)hotmail.com',@)hotmail.com'

website : 'http://coolshell.cn'

}

於是,我就可以這樣訪問:

  //以成員的方式

chenhao.name; website;

//以hash map的方式

chenhao["name"];

chenhao["email"];

chenhao["website"];

的:

  var doSomething = function(){

alert('Hello World.');

};

於是,我們可以這麼幹:

Hello, I'm “+ this.name

+ “, my email is: ” + this.email

+ “, my website is: ” + this.website;

alert(hello);

);

};

//直接賦值,這裡很像C/C++的函數指標

chenhao.Hello = sayHello;

chenhao.Hello();

相信這些東西都比較簡單,大家都懂了。 可以看到javascript物件函數是直接聲明,直接賦值,直接就用了。 runtime的動態語言。

還有比較規範的寫法是:

//我們可以看到, 其用function來做class。

var Person = function(name, email, website){

this.name = name;

this.email = email;

this.website = website; var hello = “Hello, I'm “+ this.name + “, n” +

“my email is: ” + this.email + “, n” +

“my website is: ” + this.website” + this.website ;

alert(hello);

};

};

var chenhao = new Person(“Chen Hao”, “haoel@hotmail.com”,

“http://coolcn.”);

chenhao.sayHello();

順便說一下,要刪除物件的屬性,很簡單:

delete chenhao['email']

上面的這些例子,我們可以看到這樣幾點:

◆ Javascript的資料和成員封裝很簡單。沒有類別完全是物件操作。純動態!

◆ Javascript function中的this指標很關鍵,如果沒有的話,那就是局部變數或局部函數。

◆ Javascript物件成員函數可以在使用時暫時聲明,並且把一個全域函數直接賦過去就好了。

◆ Javascript的成員函數可以在實例上進行修改,也就是說不同實例相同函數名的行為不一定一樣。

  屬性配置– Object.defineProperty

先看下面的程式碼:

  //建立物件

var chenhao = Object.create(null);

var chenhao = Object.create(null);

'name', { value: 'Chen Hao',

writable: true,

configurable: true,

enumerable: true });

//設定多個屬性

{

'email' : { value: 'haoel@hotmail.com',

writable: true,

configurable: true,

enumerable: true,,, //coolshell.cn',

writable: true,

configurable: true,

enumerable: true }

}

);

下面就說這些屬性配置是什麼意思。

writable:這個屬性的值是否可以改。

configurable:這個屬性的配置是否可以改。

enumerable:這個屬性是否能在for…in循環中遍歷出來或在Object.keys中列舉出來。

value:屬性值。

get()/set(_value):get和set存取器。

  Get/Set 訪問器

關於get/set訪問器,它的意思是用get/set來取代value(其不能和value一起使用),示例如下:

  var age = 0;

; defineProperty( chenhao,

'age', {

get: function() {return age+1;},

set: function(value) {age = value;}

enableerable : trueumhumerable : true​​idableerableer true

}

);

chenhao.age = 100; //調用set

alert(chenhao.age); //調用get 輸出101(get中+1了);

我們再看一個更調用為實用的例子-利用現有的屬性(age)透過get和set建構新的屬性(birth_year):

  Object.defineProperty( chenhao,

'birth_year',

{

'birth_year',

{

get: f) {

var d = new Date();

var y = d.getFullYear();

return ( y – this.age );

},

return

set: function(year) {

var d = new Date();

var y = d.getFullYear();

this.age = y – year;

}

}

}

this.age = y – year;

);

alert(chenhao.birth_year);

chenhao.birth_year = 2000;

alert(chenhao.age);

這樣做好像有點麻煩,你說,我為什麼不寫成下面這個樣子:o

name: “Chen Hao”,

email: “haoel@hotmail.com”,

website: “http://coolshell.cn”,

age: 100,

var d = new Date();

var y = d.getFullYear();

return ( y – this.age );

},

set birth_year(year) {

},

set birth_year(year) {

. );

var y = d.getFullYear();

this.age = y – year;

}

};

alert(chenhao.birth_year

};

alert(chenhao.birth_year); (chenhao.age);

是的,你的確可以這樣的,不過透過defineProperty()你可以做這些事:

1)設定如writable,configurable,enumerable 等這類的屬性配置。

2)動態地為一個物件加屬性。例如:一些HTML的DOM物件。

查看物件屬性配置

如果查看並管理物件的這些配置,下面有個程式可以輸出物件的屬性和配置等東西:

  //列出物件的屬性.

function listProperties(obj) {

var newLine = 」

「;

var names = Object.getOwnPropertyNames(obj);

for (var i = 0; i for (var i = 0; i for

);

document.write(prop + newLine);

// 列出物件的屬性配置(descriptor)動用getOwnPropertyDescriptor函數。

var descriptor = Object.getOwnPropertyDescriptor(obj, prop);

for (var attr in descriptor) {

document.write(“…” + attr + ': ' + descriptor[attr]); write(newLine);

}

document.write(newLine);

}

}

listProperties(chenhao);

}

listProperties(chenhao);

/<. Java很類似。 我們來看個範例:(這個範例很簡單了,我就不多說了)

  function print(text){

document.write(this.value + ' – ' + text+ '

');

}

var a = {value: 10, print : print};

var b = {value: 20, print : print};

print('hello');// this => global, output “undefined – hello”

a.print('a');// this => a, output “10 – a”

b.print('b'); // this => b, output “20 – b ”

a['print']('a'); // this => a, output “10 – a”

我們再來看看call 和apply,這兩個函數的差異就是參數的樣子不一樣,另一個就是效能不一樣,apply的效能差很多。 (關於性能,可到JSPerf 上去跑跑看看)

  print.call(a, 'a'); // this => a, output “10 – a”

print.call(b, 'b' ); // this => b, output “20 – b”

print.apply(a, ['a']); // this => a, output “10 – a”

print.apply(b , ['b']); // this => b, output “20 – b”

但是在bind後,this指針,可能會有不一樣,但是因為Javascript是動態的。如下面的例子

var p = print.bind(a);

p('a'); // this => a, output “10 – a”

p.call(b, 'b') ; // this => a, output “10 – b”

p.apply(b, ['b']); // this => a, output “10 – b”

  繼承與重載

透過上面的那些範例,我們可以透過Object.create()來實際繼承,請看下面的程式碼,Student繼承於Object。

var Person = Object.create(null);

Object.defineProperties

(

Person,

{

'name'  : {  value: 'Chen Hao'},

'name'  : {  value: 'Chen Hao'},

'email' : .com'},

'website': { value: 'http://coolshell.cn'}
}
);

Person.sayHello = function () {
var hello = “

Hello, I am “+ this.name  + “,
” +
“my email is: ” + this.email + “,
” +
“my website is: ” + this.website;
document.write(hello + “
”);

}


var Student = Object.create(Person);
Student.no = “1234567″; //學號
Student.dept = “Computer Science”; //系

//使用Person的屬性

document.write(Student.name + ' ' + Student.email + ' ' + Student.website +'
');


//使用Person的方法
Student.sayHello() ;

//重載SayHello方法
Student.sayHello = function (person) {
var hello = “

Hello, I am “+ this.name  + “,
” +
“my email is: ” + this.email + “,
” +
“my website is: ” + this.website + “,
” +
“my student no is: ” + this. no + “,
” + “,
” +
“my departent is: ” + this. dept;
document.write(hello + '
');
}
//再呼叫
Student.sayHello();

//看Student的屬性(只有no 、 dept 和重載了的sayHello)
document.write('

' + Object.keys(Student) + '
');

通用上面這個範例,我們可以看到,Person裡的屬性並沒有被真正複製到了Student中來,但是我們可以去訪問。這是因為Javascript用委託實現了這個機制。其實,這就是Prototype,Person是Student的Prototype。

當我們的程式碼需要一個屬性的時候,Javascript的引擎會先看目前的這個物件中是否有這個屬性,如果沒有的話,就會找出他的Prototype物件是否有這個屬性,一直繼續下去,直到找到或直到沒有Prototype物件。

為了證明這個事,我們可以用Object.getPrototypeOf()來檢驗一下:

Student.name = 'aaa';
//輸出aaa
document.write('

' + Student.name + '

');
//輸出Chen Hao
document.write('

' +Object.getPrototypeOf(Student).name + '

');

於是,你還可以在子物件的函數裡呼叫父物件的函數,就好像C++裡的Base::func() 一樣。於是,我們重載hello的方法就可以使用父類別的程式碼了,如下所示:

//新版的重載SayHello方法
Student.sayHello = function (person) {
Object.getPrototypeOf(this).sayHello .call(this);
var hello = “my student no is: ” + this. no + “,
” +
“my departent is: ” + this. dept;
document.write(hello + '');
}

這個很強吧。

  組合

上面的那個東西還不能滿足我們的要求,我們可能希望這些物件能真正的組合起來。為什麼要組合?因為我們都知道是這是OO設計的最重要的東西。不過,這對Javascript來並沒有支援得特別好,不好我們還是可以搞定個事。

首先,我們需要定義一個Composition的函數:(target是作用於是對象,source是來源對象),下面這個程式碼還是很簡單的,就是把source裡的屬性一個一個拿出來然後定義到target中。

  function Composition(target, source)

{

var desc = Object.getOwnPropertyDescriptor;

var prop = Object.getOwnNamesdefs;

function(key) {

def_prop(target, key, desc(source, key))

}

)

return target;

}

return target;

}

re來,我們就可以玩了

//藝術家
var Artist = Object.create(null);
Artist.sing = function() {
return this.name + ' starts singing…';
}
Artist.paint = function(turn) {

reretion this.name + ' starts painting…';

}

//運動員
var Sporter = Object.create(null);
Sporter.run = function() {
return this.name + ' starts running…';
…'; }
Sporter.swim = function() {

return this.name + ' starts swimming…';

}

Composition(Person, Artist);

document.write(Person.sing() + '
') ;

document.write(Person.paint() + '
');

Composition(Person, Sporter);

document.write(Person.run() + '
');

document.write (Person.swim() + '
');

//看看Person裡有什麼? (輸出:sayHello,sing,paint,swim,run)

document.write('

' + Object.keys(Person) + '
');

  Prototype 和繼承

我們先說說Prototype。我們先看下面的例程,這個例程不需要解釋吧,很像C語言裡的函數指針,在C語言裡這樣的東西見得多了。

var plus = function(x,y){
document.write( x + ' + ' + y + ' = ' + (x+y) + '
');

return x + y;

} ;

var minus = function(x,y){
document.write(x + ' – ' + y + ' = ' + (x-y) + '
');

return x – y;

};

var operations = {
'+': plus,

'-': minus

};

var calculate = function(x, y, operation){

return operations[operation](x, y);

return operations[operation](x, y);
return} ;

calculate(12, 4, '+');

calculate(24, 3, '-');

那麼,我們能不能把這些東西封裝起來呢,我們需要使用prototype。請看下面的範例:

  var Cal = function(x, y){

this.x = x;

this.y = y;🎜🎜}🎜

Cal.prototype.operations = {

'+': function(x, y) { return x+y;},

'-': function(x, y) { return x-y;}

};

};

Cal.prototype.calculate = function(operation){

return this.operations[operation](this.x, this.y);

};

var c = new Cal(4, 5); c.calculate('+');

c.calculate('-');

這就是prototype的用法,prototype 是javascript這個語言中最重要的內容。網路上有太多的文章介始這個東西了。說穿了,prototype就是對一物件進行擴展,其特點在於透過「複製」一個已經存在的實例來傳回新的實例,而不是新建實例。被複製的實例就是我們所稱的“原型”,這個原型是可定制的(當然,這裡沒有真正的複製,實際上只是委託)。在上面的這個例子中,我們擴充了實例Cal,讓其有了一個operations的屬性和一個calculate的方法。

這樣,我們可以透過這項特性來實現繼承。還記得我們最前面的Person吧, 下面的範例是建立一個Student來繼承Person。

function Person(name, email, website){

this.name = name;
this.email = email;
this.website = website;
};

Person.prototype.sayHello = function. hello = “Hello, I am “+ this.name  + “,
” +

“my email is: ” + this.email + “,
” +
“my website is: ” + this.website ;
return hello;
};

function Student(name, email, website, no, dept){

var proto = Object.getPrototypeOf;

proto(Student.prototype).constructor.call(this, name, ename, ename, ename.name. website);
this.no = no;
this.dept = dept;
}

// 繼承prototype

Student.prototype = Object.create(Person.prototype);


//重置構造函數

/Student. prototype.constructor = Student;


//重載sayHello()

Student.prototype.sayHello = function(){

var proto = Object.getPrototypeOf;
var hello = proto(Student.prototype).Hello. ) + '
';
hello += “my student no is: ” + this. no + “,
” +
“my departent is: ” + this. dept;
return hello;
};

var me = new Student(

「gtfx」,

「gtfx0209@gmail.com」,
「http://dyygtfx.com」,
「12345678″,
「Computer Science」
「12345678″,
「Computer Science」
); (me.sayHello());

  相容性

上面的這些程式碼並不一定能在所有的瀏覽器下都能運行,因為上面這些程式碼遵循ECMAScript 5 的規範,關於ECMAScript 5 的瀏覽器相容列表,你可以看這裡「ES5瀏覽器相容表」。

本文中的所有程式碼都在Chrome最新版中測試過了。

下面是一些函數,可以用在不相容ES5的瀏覽器中:

Object.create()函數

  function clone(proto) {

function Dummy() {};

Dummy.prototype.constructor = Dummy;

return new Dummy(); //等價於Object.create(Person);

}

var Property = clone(Person);

}

var Propertyme = clone(Person);

  function defineProperty(target, key, descriptor) {

if (descriptor.value){

target[key] = descriptor.value;

}else {

. get);

descriptor.set && target.__defineSetter__(key, descriptor.set);

}

return target

}

keys() 函數key

result = [];

for (key in object){

if (object.hasOwnProperty(key)) result.push(key)

}

return result;

}

}

ObjectO.

  function proto(object) {

return !object? null

: '__proto__' in object? object.__proto__

exp: //not exp: />g看到

bind 函數

  var slice = [].slice

function bind(fn, bound_this) { var bound_args

bound_args = slice.call(arguments, 2)

return functioncons. .call(arguments))

return fn.apply(bound_this, args) }

}

 以上就是JavaScript物件導向的內容,更多相關內容教學請追蹤PHPcnPcn. )! 

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

簡易JavaScript教學:取得HTTP狀態碼的方法

探索Go語言中的物件導向編程 探索Go語言中的物件導向編程 Apr 04, 2024 am 10:39 AM

探索Go語言中的物件導向編程

PHP高階特性:物件導向程式設計的最佳實踐 PHP高階特性:物件導向程式設計的最佳實踐 Jun 05, 2024 pm 09:39 PM

PHP高階特性:物件導向程式設計的最佳實踐

Go語言的物件導向特性解析 Go語言的物件導向特性解析 Apr 04, 2024 am 11:18 AM

Go語言的物件導向特性解析

如何在JavaScript中取得HTTP狀態碼的簡單方法 如何在JavaScript中取得HTTP狀態碼的簡單方法 Jan 05, 2024 pm 01:37 PM

如何在JavaScript中取得HTTP狀態碼的簡單方法

Golang中有類似類別的物件導向特性嗎? Golang中有類似類別的物件導向特性嗎? Mar 19, 2024 pm 02:51 PM

Golang中有類似類別的物件導向特性嗎?

如何使用WebSocket和JavaScript實現線上電子簽名系統 如何使用WebSocket和JavaScript實現線上電子簽名系統 Dec 18, 2023 pm 03:09 PM

如何使用WebSocket和JavaScript實現線上電子簽名系統

WebSocket與JavaScript:實現即時線上財經新聞的關鍵技術 WebSocket與JavaScript:實現即時線上財經新聞的關鍵技術 Dec 17, 2023 pm 11:21 PM

WebSocket與JavaScript:實現即時線上財經新聞的關鍵技術

See all articles