亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

JS面向對象的程序設計相關知識小結

2024-05-06 16:44:37
字體:
來源:轉載
供稿:網友

面向對象的語言有一個標志,即擁有類的概念,抽象實例對象的公共屬性與方法,基于類可以創建任意多個實例對象,一般具有封裝、繼承、多態的特性!但JS中對象與純面向對象語言中的對象是不同的,ECMA標準定義JS中對象:無序屬性的集合,其屬性可以包含基本值、對象或者函數??梢院唵卫斫鉃镴S的對象是一組無序的值,其中的屬性或方法都有一個名字,根據這個名字可以訪問相映射的值(值可以是基本值/對象/方法)。

一、理解對象:

第一種:基于Object對象

var person = new Object();person.name = 'My Name';person.age = 18;person.getName = function(){  return this.name;}

第二種:對象字面量方式(比較清楚的查找對象包含的屬性及方法)

var person = {  name : 'My name',  age : 18,  getName : function(){    return this.name;  }}

JS的對象可以使用‘.'操作符動態的擴展其屬性,可以使用'delete'操作符或將屬性值設置為'undefined'來刪除屬性。如下:

person.newAtt='new Attr';//添加屬性alert(person.newAtt);//new Attrdelete person.age;alert(person.age);//undefined(刪除屬性后值為undefined);

二、對象屬性類型

ECMA-262第5版定義了JS對象屬性中特征(用于JS引擎,外部無法直接訪問)。ECMAScript中有兩種屬性:數據屬性和訪問器屬性

1、數據屬性:

數據屬性指包含一個數據值的位置,可在該位置讀取或寫入值,該屬性有4個供述其行為的特性:

[[configurable]]:表示能否使用delete操作符刪除從而重新定義,或能否修改為訪問器屬性。默認為true;

[[Enumberable]]:表示是否可通過for-in循環返回屬性。默認true;

[[Writable]]:表示是否可修改屬性的值。默認true;

[[Value]]:包含該屬性的數據值。讀取/寫入都是該值。默認為undefined;如上面實例對象person中定義了name屬性,其值為'My name',對該值的修改都反正在這個位置

要修改對象屬性的默認特征(默認都為true),可調用Object.defineProperty()方法,它接收三個參數:屬性所在對象,屬性名和一個描述符對象(必須是:configurable、enumberable、writable和value,可設置一個或多個值)。

如下:(瀏覽器支持:IE9+、Firefox 4+、Chrome、Safari5+)

var person = {};Object.defineProperty(person, 'name', {  configurable: false,  writable: false,  value: 'Jack'});alert(person.name);//Jackdelete person.name;person.name = 'lily';alert(person.name);//Jack

可以看出,delete及重置person.name的值都沒有生效,這就是因為調用defineProperty函數修改了對象屬性的特征;值得注意的是一旦將configurable設置為false,則無法再使用defineProperty將其修改為true(執行會報錯:can't redefine non-configurable property);

2、訪問器屬性:

它主要包括一對getter和setter函數,在讀取訪問器屬性時,會調用getter返回有效值;寫入訪問器屬性時,調用setter,寫入新值;該屬性有以下4個特征:

[[Configurable]]:是否可通過delete操作符刪除重新定義屬性;

[[Numberable]]:是否可通過for-in循環查找該屬性;

[[Get]]:讀取屬性時調用,默認:undefined;

[[Set]]:寫入屬性時調用,默認:undefined;

訪問器屬性不能直接定義,必須使用defineProperty()來定義,如下:

var person = {  _age: 18};Object.defineProperty(person, 'isAdult', {  get: function () {    if (this._age >= 18) {      return true;    } else {      return false;    }  }});alert(person.isAdult?'成年':'未成年');//成年

從上面可知,定義訪問器屬性時getter與setter函數不是必須的,并且,在定義getter與setter時不能指定屬性的configurable及writable特性;

此外,ECMA-262(5)還提供了一個Object.defineProperties()方法,可以用來一次性定義多個屬性的特性:

var person = {};Object.defineProperties(person,{  _age:{    value:19  },  isAdult:{    get: function () {      if (this._age >= 18) {        return true;      } else {        return false;      }    }  }});alert(person.isAdult?'成年':'未成年');//成年

上述代碼使用Object.defineProperties()方法同時定義了_age及isAudlt兩個屬性的特性

此外,使用Object.getOwnPropertyDescriptor()方法可以取得給定屬性的特性:

var descriptor = Object.getOwnPropertyDescriptor(person,'_age');alert(descriptor.value);//19

對于數據屬性,可以取得:configurable,enumberable,writable和value;

對于訪問器屬性,可以取得:configurable,enumberable,get和set

三、創建對象

使用Object構造函數或對象字面量都可以創建對象,但缺點是創建多個對象時,會產生大量的重復代碼,因此下面介紹可解決這個問題的創建對象的方法

1、工廠模式

function createPerson(name, age, job) {  var o = new Object();  o.name = name;  o.age = age;  o.job = job;  o.getName = function () {    return this.name;  }  return o;//使用return返回生成的對象實例}var person = createPerson('Jack', 19, 'SoftWare Engineer');

創建對象交給一個工廠方法來實現,可以傳遞參數,但主要缺點是無法識別對象類型,因為創建對象都是使用Object的原生構造函數來完成的。

2、構造函數模式

function Person(name,age,job){  this.name = name;  this.age = age;  this.job = job;  this.getName = function () {    return this.name;  }}var person1 = new Person('Jack', 19, 'SoftWare Engineer');var person2 = new Person('Liye', 23, 'Mechanical Engineer');

使用自定義的構造函數(與普通函數一樣,只是用它來創建對象),定義對象類型(如:Person)的屬性和方法。它與工廠方法區別在于:

  • 沒有顯式地創建對象
  • 直接將屬性和方法賦值給this對象;
  • 沒有return語句;

此外,要創建Person的實例,必須使用new關鍵字,以Person函數為構造函數,傳遞參數完成對象創建;實際創建經過以下4個過程:

  1. 創建一個對象
  2. 將函數的作用域賦給新對象(因此this指向這個新對象,如:person1)
  3. 執行構造函數的代碼
  4. 返回該對象

上述由Person構造函數生成的兩個對象person1與person2都是Person的實例,因此可以使用instanceof判斷,并且因為所有對象都繼承Object,因此person1 instanceof Object也返回真:

alert(person1 instanceof Person);//true;alert(person2 instanceof Person);//true;alert(person1 instanceof Object);//true;alert(person1.constructor === person2.constructor);//ture;

雖然構造函數方式比較不錯,但也存在缺點,那就是在創建對象時,特別針對對象的屬性指向函數時,會重復的創建函數實例,以上述代碼為基礎,可以改寫為:

function Person(name,age,job){  this.name = name;  this.age = age;  this.job = job;  this.getName = new Function () {//改寫后效果與原代碼相同,不過是為了方便理解    return this.name;  }}

上述代碼,創建多個實例時,會重復調用new Function();創建多個函數實例,這些函數實例還不是一個作用域中,當然這一般不會有錯,但這會造成內存浪費。當然,可以在函數中定義一個getName = getName的引用,而getName函數在Person外定義,這樣可以解決重復創建函數實例問題,但在效果上并沒有起到封裝的效果,如下所示:

function Person(name,age,job){  this.name = name;  this.age = age;  this.job = job;  this.getName = getName;}function getName() {//到處是代碼,看著亂??!    return this.name;}

3、原型模式

JS每個函數都有一個prototype(原型)屬性,這個屬性是一個指針,指向一個對象,它是所有通過new操作符使用函數創建的實例的原型對象。原型對象最大特點是,所有對象實例共享它所包含的屬性和方法,也就是說,所有在原型對象中創建的屬性或方法都直接被所有對象實例共享。

function Person(){}Person.prototype.name = 'Jack';//使用原型來添加屬性Person.prototype.age = 29;Person.prototype.getName = function(){  return this.name;}var person1 = new Person();alert(person1.getName());//Jackvar person2 = new Person();alert(person1.getName === person2.getName);//true;共享一個原型對象的方法

原型是指向原型對象的,這個原型對象與構造函數沒有太大關系,唯一的關系是函數的prototype是指向這個原型對象!而基于構造函數創建的對象實例也包含一個內部指針為:[[prototype]]指向原型對象。

實例屬性或方法的訪問過程是一次搜索過程:

  • 首先從對象實例本身開始,如果找到屬性就直接返回該屬性值;
  • 如果實例本身不存在要查找屬性,就繼續搜索指針指向的原型對象,在其中查找給定名字的屬性,如果有就返回;

基于以上分析,原型模式創建的對象實例,其屬性是共享原型對象的;但也可以自己實例中再進行定義,在查找時,就不從原型對象獲取,而是根據搜索原則,得到本實例的返回;簡單來說,就是實例中屬性會屏蔽原型對象中的屬性;

原型與in操作符

一句話:無論原型中屬性,還是對象實例的屬性,都可以使用in操作符訪問到;要想判斷是否是實例本身的屬性可以使用object.hasOwnProperty(‘attr')來判斷;

原生對象中原型
原生對象中原型與普通對象的原型一樣,可以添加/修改屬性或方法,如以下代碼為所有字符串對象添加去左右空白原型方法:

String.prototype.trim = function(){  return this.replace(/^/s+/,'').replace(//s+$/,'');}var str = '  word space  ';alert('!'+str.trim()+'!');//!word space!

原型模式的缺點,它省略了為構造函數傳遞初始化參數,這在一定程序帶來不便;另外,最主要是當對象的屬性是引用類型時,它的值是不變的,總是引用同一個外部對象,所有實例對該對象的操作都會其它實例:

function Person() {}Person.prototype.name = 'Jack';Person.prototype.lessons = ['Math','Physics'];var person1 = new Person();person1.lessons.push('Biology');var person2 = new Person();alert(person2.lessons);//Math,Physics,Biology,person1修改影響了person2

 4、組合構造函數及原型模式
目前最為常用的定義類型方式,是組合構造函數模式與原型模式。構造函數模式用于定義實例的屬性,而原型模式用于定義方法和共享的屬性。結果,每個實例都會有自己的一份實例屬性的副本,但同時又共享著對方方法的引用,最大限度的節約內存。此外,組合模式還支持向構造函數傳遞參數,可謂是集兩家之所長。

function Person(name, age, job) {  this.name = name;  this.age = age;  this.job = job;  this.lessons = ['Math', 'Physics'];}Person.prototype = {  constructor: Person,//原型字面量方式會將對象的constructor變為Object,此外強制指回Person  getName: function () {    return this.name;  }}var person1 = new Person('Jack', 19, 'SoftWare Engneer');person1.lessons.push('Biology');var person2 = new Person('Lily', 39, 'Mechanical Engneer');alert(person1.lessons);//Math,Physics,Biologyalert(person2.lessons);//Math,Physicsalert(person1.getName === person2.getName);//true,//共享原型中定義方法

在所接觸的JS庫中,jQuery類型的封裝就是使用組合模式來實例的?。。?/p>

5、動態原型模式
組合模式中實例屬性與共享方法(由原型定義)是分離的,這與純面向對象語言不太一致;動態原型模式將所有構造信息都封裝在構造函數中,又保持了組合的優點。其原理就是通過判斷構造函數的原型中是否已經定義了共享的方法或屬性,如果沒有則定義,否則不再執行定義過程。該方式只原型上方法或屬性只定義一次,且將所有構造過程都封裝在構造函數中,對原型所做的修改能立即體現所有實例中:

function Person(name, age, job) {  this.name = name;  this.age = age;  this.job = job;  this.lessons = ['Math', 'Physics'];}if (typeof this.getName != 'function') {//通過判斷實例封裝  Person.prototype = {    constructor: Person,//原型字面量方式會將對象的constructor變為Object,此外強制指回Person    getName: function () {      return this.name;    }  }}var person1 = new Person('Jack', 19, 'SoftWare Engneer');person1.lessons.push('Biology');var person2 = new Person('Lily', 39, 'Mechanical Engneer');alert(person1.lessons);//Math,Physics,Biologyalert(person2.lessons);//Math,Physicsalert(person1.getName === person2.getName);//true,//共享原型中定義方法

注:以上內容參考《JavaScript 高級程序設計》第3版


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美一区二区大胆人体摄影专业网站| 成人激情视频免费在线| 久久久女女女女999久久| www.日韩不卡电影av| 欧美性受xxxx白人性爽| 精品国产自在精品国产浪潮| 国产成人亚洲综合青青| 一区二区成人av| 国内精品模特av私拍在线观看| 亚洲女性裸体视频| 成人福利网站在线观看| 中文字幕视频一区二区在线有码| 久久久噜噜噜久久中文字免| 国产综合久久久久久| 成人情趣片在线观看免费| 久久精品99国产精品酒店日本| 国产精品极品美女在线观看免费| 成人激情视频网| 精品久久久久久久久久| 亚洲欧美三级伦理| 亚洲欧美日韩中文在线| 成人激情电影一区二区| 国产欧美欧洲在线观看| 97久久伊人激情网| 中文字幕精品—区二区| 国产一区二区日韩精品欧美精品| 日韩欧美国产网站| 欧美一区二区视频97| 亚洲一区二区在线播放| 亚洲视频视频在线| 韩剧1988在线观看免费完整版| 在线观看精品国产视频| 日韩黄在线观看| 欧美国产乱视频| 超碰日本道色综合久久综合| 色在人av网站天堂精品| 欧美亚洲另类在线| 久久久久久久久久久91| 国产成人亚洲综合91| 91九色在线视频| 久久97精品久久久久久久不卡| 久久精品99久久久久久久久| 亚洲免费视频网站| 亚洲欧美日韩精品久久| 亚洲精品久久久久久久久久久久| 欧美成aaa人片免费看| 精品久久久免费| 日韩精品中文字幕视频在线| 日韩精品视频在线| 国产一区二区日韩精品欧美精品| 国产不卡精品视男人的天堂| 亚洲美女www午夜| 国产精品自拍小视频| 国产成人精品日本亚洲| 98精品国产自产在线观看| 精品国产拍在线观看| 国产成人在线播放| 亚洲国产日韩欧美在线图片| 成人亚洲综合色就1024| 亚洲另类欧美自拍| 亚洲日韩第一页| www.久久久久| 日韩免费黄色av| 成人在线观看视频网站| 久久影视电视剧免费网站| 91夜夜未满十八勿入爽爽影院| 狠狠久久五月精品中文字幕| 欧美精品videofree1080p| 欧美一乱一性一交一视频| 亚洲第一区中文字幕| 夜夜嗨av色综合久久久综合网| 91久久夜色精品国产网站| 日韩电影中文 亚洲精品乱码| 97人人模人人爽人人喊中文字| 欧美一级电影久久| 91精品久久久久久久久久久久久久| 中文字幕日韩av综合精品| 中文字幕亚洲综合| 日韩美女主播视频| 亚洲精品成人网| 国产精品69精品一区二区三区| 亚洲日本中文字幕免费在线不卡| 日韩高清a**址| 青草青草久热精品视频在线观看| 91精品久久久久久久久久久| 久久视频免费观看| 欧美黄色小视频| 91在线视频一区| 亚洲综合国产精品| 欧美亚洲一区在线| 久久电影一区二区| 超碰精品一区二区三区乱码| 国产精品久久久久久久一区探花| 国产精品私拍pans大尺度在线| 亚洲最大福利视频网| 精品亚洲va在线va天堂资源站| 在线播放国产一区二区三区| 欧美中文字幕视频在线观看| 欧美激情一区二区三区久久久| 久久久久久成人精品| 久久精品国产精品| 国产精品久久久av久久久| 日韩欧美亚洲国产一区| 92版电视剧仙鹤神针在线观看| 91精品国产免费久久久久久| 亚洲欧洲在线看| 美女少妇精品视频| 欧美在线视频一区二区| 欧美一级大胆视频| 91精品免费视频| 国产精品香蕉av| 亚洲视频一区二区三区| 亚洲аv电影天堂网| 色综合久久88色综合天天看泰| 欧美亚洲视频在线观看| 欧美成aaa人片在线观看蜜臀| 久久精品国产一区二区三区| 国产亚洲精品久久久久久牛牛| 一区二区三区四区视频| 欧美激情高清视频| 亚洲欧美日韩一区二区在线| 日韩一中文字幕| 精品久久久久久中文字幕大豆网| 国产一区二区三区精品久久久| 中文字幕日本精品| 日韩av不卡电影| 国产亚洲精品美女久久久久| 日韩在线观看免费| 在线中文字幕日韩| 亚洲精品美女在线| 亚洲欧美国产日韩天堂区| 欧美人交a欧美精品| 欧洲永久精品大片ww免费漫画| 亚洲最大的网站| 中文字幕日韩av综合精品| 一本色道久久综合亚洲精品小说| 中文字幕在线精品| 亚洲国产成人精品电影| 久久久久久91香蕉国产| 国产亚洲精品高潮| 国产精品久久久久久久久久三级| 在线视频欧美性高潮| 精品一区二区三区三区| 国产69久久精品成人看| 夜色77av精品影院| 亚洲国产精品成人av| 91tv亚洲精品香蕉国产一区7ujn| 欧美激情精品在线| 亚洲人成电影在线播放| 91po在线观看91精品国产性色| 亚洲加勒比久久88色综合| 欧美电影免费观看电视剧大全| 久久久www成人免费精品张筱雨| 欧美美最猛性xxxxxx| 欧美性在线视频| 精品视频在线导航| 另类少妇人与禽zozz0性伦| 亚洲精品美女免费| 久久久免费精品视频| 日韩av在线一区| 91极品女神在线| 日本欧美黄网站| 亚洲综合日韩中文字幕v在线| 伊人久久久久久久久久久|