日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

javascript 在对象中使用 定时器_如何使用JavaScript 面向对象编程

發(fā)布時間:2023/12/10 javascript 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 javascript 在对象中使用 定时器_如何使用JavaScript 面向对象编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學習目標

理解面向對象開發(fā)思想

掌握 JavaScript 面向對象開發(fā)相關模式

面向對象介紹

什么是對象

Everything is object (一切皆對象)

我們可以從兩個層次來理解對象:

(1) 對象是單個事物的抽象。

????一本書、一輛汽車、一個人都可以是對象,一個數據庫、一張網頁、一個與遠程服務器的連接也可以是對象。當實物被抽象成對象,實物之間的關系就變成了對象之間的關系,從而就可以模擬現實情況,針對對象進行編程。

(2) 對象是一個容器,封裝了屬性(property)和方法(method)。

????屬性是對象的狀態(tài),方法是對象的行為(完成某種任務)。比如,我們可以把動物抽象為animal對象,使用“屬性”記錄具體是那一種動物,使用“方法”表示動物的某種行為(奔跑、捕獵、休息等等)。

????在實際開發(fā)中,對象是一個抽象的概念,可以將其簡單理解為:數據集或功能集。ECMAScript-262 把對象定義為:無序屬性的集合,其屬性可以包含基本值、對象或者函數。嚴格來講,這就相當于說對象是一組沒有特定順序的值。對象的每個屬性或方法都有一個名字,而每個名字都 映射到一個值。

提示:每個對象都是基于一個引用類型創(chuàng)建的,這些類型可以是系統(tǒng)內置的原生類型,也可以是開發(fā)人員自定義的類型。

什么是面向對象

面向對象不是新的東西,它只是過程式代碼的一種高度封裝,目的在于提高代碼的開發(fā)效率和可維護性。

????面向對象編程 —— Object Oriented Programming,簡稱 OOP ,是一種編程開發(fā)思想。它將真實世界各種復雜的關系,抽象為一個個對象,然后由對象之間的分工與合作,完成對真實世界的模擬。

????在面向對象程序開發(fā)思想中,每一個對象都是功能中心,具有明確分工,可以完成接受信息、處理數據、發(fā)出信息等任務。因此,面向對象編程具有靈活、代碼可復用、高度模塊化等特點,容易維護和開發(fā),比起由一系列函數或指令組成的傳統(tǒng)的過程式編程(procedural programming),更適合多人合作的大型軟件項目。

面向對象與面向過程區(qū)別:

  • 面向過程就是親力親為,事無巨細,面面俱到,步步緊跟,有條不紊。

  • 面向對象就是找一個對象,指揮得結果。

  • 面向對象將執(zhí)行者轉變成指揮者。

  • 面向對象不是面向過程的替代,而是面向過程的封裝。

面向對象的特性:

  • 封裝性

  • 繼承性

  • 多態(tài)性

JavaScript 中面向對象的基本體現

????在 JavaScript 中,所有數據類型都可以視為對象,當然也可以自定義對象。自定義的對象數據類型就是面向對象中的類( Class )的概念。

????我們以一個例子來說明面向過程和面向對象在程序流程上的不同之處。

????假設我們要處理學生的成績表,為了表示一個學生的成績,面向過程的程序可以用一個對象表示:

var std1 = { name: '張三', score: 98 }var std2 = { name: '李四', score: 81 }

????而處理學生成績可以通過函數實現,比如打印學生的成績:

function printScore (student) { console.log('姓名:' + student.name + ' ' + '成績:' + student.score)}

????如果采用面向對象的程序設計思想,我們首選思考的不是程序的執(zhí)行流程, 而是 Student 這種數據類型應該被視為一個對象,這個對象擁有 name 和 score 這兩個屬性(Property)。如果要打印一個學生的成績,首先必須創(chuàng)建出這個學生對應的對象,然后,給對象發(fā)一個 printScore 消息,讓對象自己把自己的數據打印出來。

抽象數據行為模板(Class):

function Student (name, score) { this.name = name this.score = score}Student.prototype.printScore = function () { console.log('姓名:' + this.name + ' ' + '成績:' + this.score)}

根據模板創(chuàng)建具體實例對象(Instance):

var std1 = new Student('張三', 98)var std2 = new Student('李四', 81)

實例對象具有自己的具體行為(給對象發(fā)消息):

std1.printScore() // => 姓名:張三 成績:98std2.printScore() // => 姓名:李四 成績 81

????面向對象的設計思想是從自然界中來的,因為在自然界中,類(Class)和實例(Instance)的概念是很自然的。Class 是一種抽象概念,比如我們定義的 Class——Student ,是指學生這個概念, 而實例(Instance)則是一個個具體的 Student ,比如, 張三 和 李四 是兩個具體的 Student 。

面向對象的設計思想是:

  • 抽象出 Class

  • 根據 Class 創(chuàng)建 Instance

  • 指揮 Instance 得結果

????面向對象的抽象程度比函數要高,因為一個 Class 既包含數據,又包含操作數據的方法。

JavaScript 如何創(chuàng)建對象

字面量方式

????我們可以直接通過 new Object()?創(chuàng)建:

var person = new Object()person.name = '張三'person.age = 18person.sayName = function () { console.log(this.name)}

????每次創(chuàng)建通過 new Object()?比較麻煩,所以可以通過它的簡寫形式對象字面量來創(chuàng)建:

var person = { name: '張三', age: 18, sayName: function () { console.log(this.name) }}

????上面的寫法是沒有問題的,但是假如我們要生成兩個 person 實例對象呢?

var person1 = { name: '張三', age: 18, sayName: function () { console.log(this.name) }}var person2 = { name: '李四', age: 16, sayName: function () { console.log(this.name) }}

????通過上面的代碼我們不難看出,這樣寫的代碼太過冗余,重復性太高。

簡單方式的改進:工廠函數

????我們可以寫一個函數,解決上邊代碼重復的問題:

function createPerson (name, age) { return { name: name, age: age, sayName: function () { console.log(this.name) } }}

????生成實例對象:

var p1 = createPerson('張三', 18)var p2 = createPerson('李四', 18)

????這樣封裝比上邊的方式好多了,通過工廠模式我們解決了創(chuàng)建多個相似對象代碼冗余的問題, 但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)。

更優(yōu)雅的工廠函數:構造函數

????一種更優(yōu)雅的工廠函數就是下面這樣,構造函數:

function Person (name, age) { this.name = name this.age = age this.sayName = function () { console.log(this.name) }}var p1 = new Person('張三', 18)p1.sayName() // => 張三var p2 = new Person('李四', 23)p2.sayName() // => 李四

????在上面的示例中,Person()?函數取代了 createPerson()?函數,但是實現效果是一樣的。這是為什么呢?

????我們注意到,Person()?中的代碼與?createPerson()?有以下幾點不同之處

  • 沒有顯示的創(chuàng)建對象

  • 直接將屬性和方法賦給了?this?對象

  • 沒有?return?語句

  • 函數名使用的是大寫的?Person

  • 構造函數代碼執(zhí)行過程

    ????要創(chuàng)建 Person 實例,則必須使用 new 操作符。以這種方式調用構造函數會經歷以下 4 個步驟:

  • 創(chuàng)建一個新對象。

  • 將構造函數的作用域賦給新對象(因此 this 就指向了這個新對象)。

  • 執(zhí)行構造函數中的代碼。

  • 返回新對象。

  • ????下面是具體的偽代碼:

    function Person (name, age) { // 當使用 new 操作符調用 Person() 的時候,實際上這里會先創(chuàng)建一個對象 // var instance = {} // 然后讓內部的 this 指向 instance 對象 // this = instance // 接下來所有針對 this 的操作實際上操作的就是 instance this.name = name this.age = age this.sayName = function () { console.log(this.name) } // 在函數的結尾處會將 this 返回,也就是 instance // return this}

    構造函數和實例對象的關系

    ????使用構造函數的好處不僅僅在于代碼的簡潔性,更重要的是我們可以識別對象的具體類型了。在每一個實例對象中的_proto_中同時有一個 constructor 屬性,該屬性指向創(chuàng)建該實例的構造函數:

    console.log(p1.constructor === Person) // => trueconsole.log(p2.constructor === Person) // => trueconsole.log(p1.constructor === p2.constructor) // => true

    ????對象的 constructor 屬性最初是用來標識對象類型的, 但是,如果要檢測對象的類型,還是使用 instanceof 操作符更可靠一些:

    console.log(p1 instanceof Person) // => trueconsole.log(p2 instanceof Person) // => true

    總結:

  • 構造函數是根據具體的事物抽象出來的抽象模板。

  • 實例對象是根據抽象的構造函數模板得到的具體實例對象。

  • 每一個實例對象都具有一個 constructor 屬性,指向創(chuàng)建該實例的構造函數。( 此處constructor 是實例的屬性的說法不嚴謹,具體后面的原型會講到)

  • 可以通過實例的 constructor 屬性判斷實例和構造函數之間的關系。(這種方式不嚴謹,推薦使用 instanceof 操作符,后面學原型會解釋為什么)

  • 構造函數的問題

    ????使用構造函數帶來的最大的好處就是創(chuàng)建對象更方便了,但是其本身也存在一個浪費內存的問題:

    function Person (name, age) { this.name = name this.age = age this.type = '學生' this.sayHello = function () { console.log('hello ' + this.name) }}var p1 = new Person('王五', 18)var p2 = new Person('李四', 16)

    ????上邊的代碼,從表面看上好像沒什么問題,但是實際上這樣做,有一個很大的弊端。那就是對于每一個實例對象,type和 sayHello 都是一模一樣的內容, 每一次生成一個實例,都必須為重復的內容,多占用一些內存,如果實例對象很多,會造成極大的內存浪費。

    console.log(p1.sayHello === p2.sayHello) // => false

    ????對于這種問題我們可以把需要共享的函數定義到構造函數外部:

    function sayHello = function () { console.log('hello ' + this.name)}function Person (name, age) { this.name = name this.age = age this.type = '學生' this.sayHello = sayHello}var p1 = new Person('王五', 18)var p2 = new Person('李四', 16)console.log(p1.sayHello === p2.sayHello) // => true

    ????這樣確實可以了,但是如果有多個需要共享的函數的話就會造成全局命名空間沖突的問題。如何解決這個問題呢?你肯定想到了可以把多個函數放到一個對象中用來避免全局命名空間沖突的問題:

    var fns = { sayHello: function () { console.log('hello ' + this.name) }, sayAge: function () { console.log(this.age) }}function Person (name, age) { this.name = name this.age = age this.type = '學生' this.sayHello = fns.sayHello this.sayAge = fns.sayAge}var p1 = new Person('王五', 18)var p2 = new Person('李四', 16)console.log(p1.sayHello === p2.sayHello) // => trueconsole.log(p1.sayAge === p2.sayAge) // => true

    ????至此,我們利用自己的方式基本上解決了構造函數的內存浪費問題。但是代碼看起來還是那么的格格不入,那有沒有更好的方式呢?

    原型

    更好的解決方案:prototype

    ??? Javascript 規(guī)定,每一個構造函數都有一個 prototype 屬性,指向另一個對象。這個對象的所有屬性和方法,都會被構造函數的實例繼承。

    ????這也就意味著,我們可以把所有對象實例需要共享的屬性和方法直接定義在 prototype 對象上。

    function Person (name, age) { this.name = name this.age = age}console.log(Person.prototype)Person.prototype.type = '學生'Person.prototype.sayName = function () { console.log(this.name)}var p1 = new Person(...)var p2 = new Person(...)console.log(p1.sayName === p2.sayName) // => true

    ????這時所有實例的 type 屬性和 sayName()?方法, 其實都是同一個內存地址,指向 prototype 對象,因此就提高了運行效率。

    ?構造函數、實例、原型三者之間的關系

    ????任何函數都有一個 prototype 屬性,該屬性是一個對象。

    function F () {}console.log(F.prototype) // => objectF.prototype.sayHi = function () { console.log('hi!')}

    ????構造函數的 prototype 對象默認都有一個 constructor 屬性,指向 prototype 對象所在函數。

    console.log(F.constructor === F) // => true

    ????通過構造函數得到的實例對象內部會包含一個指向構造函數的 prototype 對象的指針?__proto__。

    var instance = new F()console.log(instance.__proto__ === F.prototype) // => true

    `__proto__` 是非標準屬性。

    實例對象可以直接訪問原型對象成員:

    instance.sayHi() // => hi!

    總結:

  • 任何函數都具有一個 prototype 屬性,該屬性是一個對象。

  • 構造函數的 prototype 對象默認都有一個 constructor 屬性,指向 prototype 對象所在函數。

  • 通過構造函數得到的實例對象內部會包含一個指向構造函數的 prototype 對象的指針?__proto__。

  • 所有實例都直接或間接繼承了原型對象的成員。

  • 屬性成員的搜索原則:原型鏈

    ????了解了?構造函數-實例-原型對象?三者之間的關系后,接下來我們來解釋一下為什么實例對象可以訪問原型對象中的成員

    ????每當代碼讀取某個對象的某個屬性時,都會執(zhí)行一次搜索,目標是具有給定名字的屬性。

  • 搜索首先從對象實例本身開始。

  • 如果在實例中找到了具有給定名字的屬性,則返回該屬性的值。

  • 如果沒有找到,則繼續(xù)搜索指針指向的原型對象,在原型對象中查找具有給定名字的屬性。

  • 如果在原型對象中找到了這個屬性,則返回該屬性的值。

  • 也就是說,在我們調用 person1.sayName()?的時候,會先后執(zhí)行兩次搜索:

  • 首先,解析器會問:

    “實例 person1 有 sayName 屬性嗎?

    ”答:

    “沒有。

  • 然后,它繼續(xù)搜索,再問:“ person1 的原型有 sayName 屬性嗎?”答:“有。

  • 于是,它就讀取那個保存在原型對象中的函數。

  • 當我們調用 person2.sayName() 時,將會重現相同的搜索過程,得到相同的結果。

  • ????這就是多個對象實例共享原型所保存的屬性和方法的基本原理。

    總結:

  • 先在自己身上找,找到即返回。

  • 自己身上找不到,則沿著原型鏈向上查找,找到即返回。

  • 如果一直到原型鏈的末端還沒有找到,則返回 undefined。

  • 實例對象讀寫原型對象成員

    讀取:

  • 先在自己身上找,找到即返回。

  • 自己身上找不到,則沿著原型鏈向上查找,找到即返回。

  • 如果一直到原型鏈的末端還沒有找到,則返回 undefined。

  • 值類型成員寫入(實例對象.值類型成員 = xx):

  • 當實例期望重寫原型對象中的某個普通數據成員時實際上會把該成員添加到自己身上。

  • 也就是說該行為實際上會屏蔽掉對原型對象成員的訪問。

  • 引用類型成員寫入(實例對象.引用類型成員 = xx):同上。

    復雜類型修改(實例對象.成員.xx = xx):

  • 同樣會先在自己身上找該成員,如果自己身上找到則直接修改。

  • 如果自己身上找不到,則沿著原型鏈繼續(xù)查找,如果找到則修改。

  • 如果一直到原型鏈的末端還沒有找到該成員,則報錯(實例對象.undefined.xx = xx)。

  • 更簡單的原型語法

    ????我們注意到,前面例子中每添加一個屬性和方法就要敲一遍 Person.prototype 。?為減少不必要的輸入,更常見的做法是用一個包含所有屬性和方法的對象字面量來重寫整個原型對象:

    function Person (name, age) { this.name = name this.age = age}Person.prototype = { type: '學生', sayHello: function () { console.log('我叫' + this.name + ',我今年' + this.age + '歲了') }}

    ????在該示例中,我們將 Person.prototype 重置到了一個新的對象。這樣做的好處就是為 Person.prototype 添加成員簡單了,但是也會帶來一個問題,那就是原型對象丟失了 constructor 成員。

    ????所以,我們?yōu)榱吮3?constructor 的指向正確,建議的寫法是:

    function Person (name, age) { this.name = name this.age = age}Person.prototype = { constructor: Person, // => 手動將 constructor 指向正確的構造函數 type: '學生', sayHello: function () { console.log('我叫' + this.name + ',我今年' + this.age + '歲了') }}

    原生對象的原型

    所有函數都有 prototype 屬性對象。

    Object.prototype

    Function.prototype

    Array.prototype

    String.prototype

    Number.prototype

    Date.prototype

    ...

    ????為數組對象和字符串對象擴展原型方法:

    //為內置對象添加原型方法//我們在系統(tǒng)的對象的原型中添加方法,相當于在改變源碼//我希望字符串中有一個倒序字符串的方法String.prototype.myReverse = function() {for (var i = this.length - 1; i >= 0; i--) {console.log(this[i]);}};var str = "abcdefg";str.myReverse();//為Array內置對象的原型對象中添加方法Array.prototype.mySort = function() {for (var i = 0; i < this.length - 1; i++) {for (var j = 0; j < this.length - 1 - i; j++) {if (this[j] < this[j + 1]) {var temp = this[j];this[j] = this[j + 1];this[j + 1] = temp;} //end if} // end for} //end for};var arr = [100, 3, 56, 78, 23, 10];arr.mySort();console.log(arr);String.prototype.sayHi = function() {console.log(this + "哈哈,我又變帥了");};//字符串就有了打招呼的方法var str2 = "小楊";str2.sayHi();

    原型對象的一些問題

    • 共享數組

    • 共享對象

    ????如果真的希望可以被實例對象之間共享和修改這些共享數據那就不是問題。但是如果不希望實例之間共享和修改這些共享數據則會出現問題。一個更好的建議是,最好不要讓實例之間互相共享數組或者對象成員,一旦修改的話會導致數據的走向很不明確而且難以維護。

    原型對象使用建議:

  • 私有成員(一般就是非函數成員)放到構造函數中。

  • 共享成員(一般就是函數)放到原型對象中。

  • 如果重置了 prototype 記得修正 constructor 的指向。

  • 總結

    以上是生活随笔為你收集整理的javascript 在对象中使用 定时器_如何使用JavaScript 面向对象编程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产日韩欧美 | 69pao| 欧美日韩卡一卡二 | 一区二区毛片 | 亚洲色图美腿丝袜 | 欧美大片一区二区三区 | 91成人免费电影 | 无码一区二区三区视频 | 国产一级二级三级在线 | 超碰997 | 91免费黄| 欧美人吸奶水吃奶水 | 国产精品videossex久久发布 | 爱爱网站免费 | 91视频网 | 日产国产亚洲精品系列 | 精品久久久无码中文字幕边打电话 | 私人午夜影院 | 国产91丝袜在线播放 | 亚洲产国偷v产偷v自拍涩爱 | 亚洲第一综合网站 | 天天操天天干天天操 | 欧美黄色视屏 | 日本在线免费视频 | 91亚洲一区 | 精品动漫一区二区三区的观看方式 | 久久久久久久久久久国产 | 亚洲国产成人在线视频 | jlzzzjlzzz国产免费观看 | 国产成人午夜高潮毛片 | 亚洲中文字幕一区二区 | 中文字幕在线免费视频 | 欧美日韩视频免费观看 | 精品国产一区二区三区四区阿崩 | 国产高清视频一区二区 | 色乱码一区二区三区 | 欧美成人精品在线观看 | 特级西西444www高清大胆免费看 | 亚洲播放器 | 欧美亚洲黄色 | 国产午夜精品一区二区三区四区 | 欧美色图在线视频 | 寡妇激情做爰呻吟 | 日韩和一区二区 | 青青草激情视频 | 免费在线观看视频 | 日日摸日日碰夜夜爽av | 精品97人妻无码中文永久在线 | 911色 | 拔插拔插华人 | 二男一女一级一片 | 欧美日韩一区三区 | 可以免费看av的网站 | 91精品久久久久久久久久入口 | 黄色网入口 | 瑟瑟视频在线免费观看 | 一区二区欧美在线观看 | 免费观看全黄做爰的视频 | 国产不卡av在线播放 | 国产精品电影一区二区 | 国产成人精品午夜福利Av免费 | 成年人黄色在线观看 | 97影视 | 国产又黄又粗又爽 | 四色成人av永久网址 | 男ji大巴进入女人视频 | 国产嫩草在线 | 91爱看 | 日韩成人小视频 | 欧美特黄一级 | 国产精品一区二区白浆 | 国产情侣酒店自拍 | 中文字幕www | 女人高潮潮呻吟喷水 | 人人爱爱 | 深夜成人福利视频 | 嫩草视频在线观看 | 国偷自拍 | 成人av高清| 特级淫片裸体免费看 | 一本到免费视频 | 四虎影成人精品a片 | 乱人伦中文字幕 | 欧美日韩黄色大片 | 台湾佬成人中文网222vvv | 天天撸夜夜操 | 精品国产99久久久久久宅男i | 欧美嫩交 | 爆操网站| 91av麻豆 | 国产理论片在线观看 | 亚洲中文在线一区 | 国产一区二区网站 | 精品人伦一区二区三电影 | 大地资源高清播放在线观看 | 亚洲永久在线观看 | 欧美三级午夜理伦三级中视频 | 四虎精品一区二区 | 国产精品久久久久久亚洲调教 |