摘要:面向?qū)ο笤兔嫦驅(qū)ο笙腴_一個(gè)車,你不需要自己去造一個(gè)車,只需要一把鑰匙,車對于你來說就是一個(gè)對象。使用構(gòu)造函數(shù)模式和原型模式組合初學(xué)筆記,個(gè)人記錄備忘,如有謬誤,歡迎指正。
面向?qū)ο?、原?/b> 面向?qū)ο?/b>
想開一個(gè)車,你不需要自己去造一個(gè)車,只需要一把鑰匙,車對于你來說就是一個(gè)"對象"。
在JavaScript中的"對象", 具有屬性,當(dāng)屬性的值是一個(gè)函數(shù)時(shí),那么此屬性就是這個(gè)對象的方法.訪問屬性的方式參考Object介紹
首先想到的是字面量創(chuàng)建對象,其次是創(chuàng)建一個(gè)對象實(shí)例,然后一次對對象屬性進(jìn)行賦值.但是無論這兩種那個(gè)方法都有個(gè)缺點(diǎn),當(dāng)需要重復(fù)創(chuàng)建大量相同的對象時(shí),產(chǎn)生大量代碼這是很不理想的,這時(shí)想到函數(shù)的一個(gè)功能就是講重復(fù)代碼進(jìn)行簡化,以便多次使用,那么構(gòu)造函數(shù)形式創(chuàng)建多個(gè)對象方式就是理想的選擇了.
什么是構(gòu)造函數(shù)?function outPut() { console.log("hello") } function Person (name,age) { this.name2 = name; this.age2 = age; this.sayName = function () { console.log("this.name2") }; } var person2 = new person("Kangkang" , 20) // 分別調(diào)用
這里有幾點(diǎn)需要注意,首先是這個(gè)this是誰? new操作符有什么作用?
this指向的創(chuàng)建的實(shí)例,這里指的是 person2, 而new操作符可以創(chuàng)建一個(gè)對象實(shí)例.
使用new通過構(gòu)造函數(shù)方式創(chuàng)建對象的實(shí)際包含的步驟有:創(chuàng)建一個(gè)新對象,
將構(gòu)造函數(shù)的作用域賦給新對象,此時(shí)this已經(jīng)指向新對象,操作this等同操作新對象
執(zhí)行構(gòu)造函數(shù)里的代碼
返回創(chuàng)建的新對象
如何檢測對象的類型? (檢測操作符右邊的函數(shù)原型是否存在于左邊的實(shí)例的原型鏈上)使用instanceof 操作符,返回布爾值.
p1 instanceof Person; p1 instanceof Object;
第二個(gè)檢測,無論是自己創(chuàng)建的構(gòu)造函數(shù)對象還是字面量對象,均為true,因?yàn)樗麄兙^承自O(shè)bject. 對于某個(gè)構(gòu)造函數(shù)創(chuàng)建的實(shí)例當(dāng)其構(gòu)造函數(shù)的原型被改變后使用此操作符發(fā)現(xiàn)返回false ,原因在于在實(shí)例的原型鏈上構(gòu)造函數(shù)的原型是舊的對象,不是新的對象,自然也就不對了。instanceof-MDN
那么對于構(gòu)造函數(shù)創(chuàng)建的對象里的方法,每次創(chuàng)建實(shí)例時(shí)都要重新創(chuàng)建,如何解決?思路是將這個(gè)方法提到實(shí)例的外面去,如果是全局對象不就可以直接調(diào)用了嗎?可是全局函數(shù)對于封裝來說可沒好處,所以原型模式也就有了用處.
原型原型是定義能夠被對象實(shí)例所使用的屬性和函數(shù)的一種方式.原型的屬性會(huì)變成實(shí)例的屬性.
這段話不容易理解.一點(diǎn)點(diǎn)分析,對象的原型屬性(prototype)指向的是一個(gè)對象,對象里存的屬性和方法在對象實(shí)例后(即構(gòu)造函數(shù)方法創(chuàng)建的新對象) 可以被實(shí)例對象訪問使用.
function Person() { } Person.prototype.name = "Kangkang" Person.prototype.age = 20 Person.prototype.sayName = function () { console.log(this.name) } var person1 = new Person() person1.sayName() // "Kangkang" var person2 = new Person() person2.sayName() //"Kangkang" console.log(person1.sayName == person2.sayName) //true var person3 = new Person() person3.name = "Mary" person3.sayName() //"Mary"
在函數(shù)創(chuàng)建的時(shí)候,prototype屬性就被創(chuàng)建出來了,通過構(gòu)造函數(shù)生成的實(shí)例在瀏覽器下支持一個(gè)屬性__proto__ 查看prototype(原型里的對象)
如圖所示
顯示的是當(dāng)一個(gè)實(shí)例在自己屬性中找不到相應(yīng)的方法或者屬性時(shí)往上一層尋找的情況。
檢測某個(gè)屬性屬于實(shí)例還是原型:
person1.hasOwnProperty("name") 當(dāng)這個(gè)屬性是實(shí)例的返回true,是原型的返回false
注意到在實(shí)例中重寫某個(gè)屬性會(huì)阻止訪問原型中的這個(gè)屬性,可是不會(huì)影響到原型中的屬性。
多帶帶操作的in操作符
使用這個(gè)操作符可以檢測某個(gè)屬性是否可以通過對象訪問,這也就指的是無論這個(gè)屬性是實(shí)例中的還是原型中的,要知道實(shí)例可以通過 __proto__ 訪問,由上圖可知
"name" in Person1 可以訪問返回true,否則返回false
這個(gè)操作符可以和上面的hasOwnperty() 結(jié)合使用判斷某個(gè)屬性是否存在且存在于哪里。
如何為原型添加屬性和方法?由上面介紹可知,通過Person.prototype.name = "kangkang"
這種方法甚是繁瑣,多個(gè)屬性、方法將會(huì)導(dǎo)致反復(fù)的輸入,所以對象字面量的書寫方式就能很好解決這個(gè)問題。
function Person () { } Person.prototype = { name : "Kangkang", age: 20, job: "student", sayName = function() { console.log(name) } }防止實(shí)例與原型的鏈斷開
謹(jǐn)慎在初始化原型后再將其改變?yōu)榱硗庖粋€(gè)對象
function Person () { } var friend = new Person() Person.prototype.sayHi = function() { console.log("hi") } friend.sayHI(); // 在創(chuàng)建對象后再對原型添加方法依然有效
下面這種情況:
function Person () { } var friend = new Person() Person.prototype = { name : "Kangkang", age: 20, job: "student", friends: ["xiaojun","xiaoming"], sayName : function() { console.log(name) } friend.sayName();// error
這種情況相當(dāng)于在原型初始化后又重新生成對象并且賦值,而原來的實(shí)例是指向初始化時(shí)的對象地址,故無法訪問新的原型里的屬性和方法.
原型對象和屬性的區(qū)別?如下程序:
function Person () { } Person.prototype = { name : "Kangkang", age: 20, job: "student", friends: ["xiaojun","xiaoming"], sayName : function() { console.log(name) } } var person6 = new Person() var person7 = new Person() // person6.name = "Mary" // console.log(person6.name) // console.log(person7.name) // person6.sayName = function() { // console.log("hi") // } person6.friends.push("xiaohong") console.log(person6.friends) console.log(person7.friends) console.log(person6.sayName == person7.sayName)
由上面的代碼得出:
當(dāng)對原型中基本類型值屬性和方法在實(shí)例中重新添加會(huì)阻止尋找到原型中的屬性和方法,當(dāng)用delete 操作符刪除后依然可以找到原型中的屬性和方法,也就是說在實(shí)例中重定義這兩種情況不會(huì)影響原型中的屬性和方法,但是如果原型中的屬性對應(yīng)的值是引用類型,由于引用類型的特性,實(shí)例得到了相同的這個(gè)屬性的地址,又由于原型是實(shí)例公用的方法,所以當(dāng)任一實(shí)例操作這個(gè)引用值屬性時(shí)都會(huì)影響到其他這個(gè)對象的實(shí)例。所以組合使用構(gòu)造函數(shù)和原型也就很好解決這個(gè)問題。
使用構(gòu)造函數(shù)模式和原型模式組合function Person (name, age, job) { this.name = name this.age = age this.job = job this.friends = ["kangkang","mary"] } Person.prototype = { constructor : Person, sayName : function () { console.log(this.name) } } var person1 = new Person("xiaojun",22,"student") var person2 = new Person("xiaowang", 21, "student") person1.friends.push("xiaozhang") console.log(person1.friends) // ["kangkang", "mary", "xiaozhang"] console.log(person2.friends) // ["kangkang", "mary"] console.log(person1.friends === person2.friends) //false console.log(person1.sayName === person2.sayName) //true
初學(xué)筆記,個(gè)人記錄備忘,如有謬誤,歡迎指正。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/94358.html
摘要:抽象類和接口小記抽象類和接口實(shí)現(xiàn)了的多態(tài)多態(tài)是面向?qū)ο蟪绦蛘Z言的核心在項(xiàng)目開發(fā)過程中其實(shí)很少使用抽象類接口用得比較多今天小記一下抽象類和接口的區(qū)別抽象類抽象類不能被實(shí)例化抽象類可以繼承可以定義變量可以定義構(gòu)造方法抽象方法的要顯式的寫出來其子 Java抽象類和接口小記 Java抽象類和接口實(shí)現(xiàn)了java的多態(tài).多態(tài)是面向?qū)ο蟪绦蛘Z言的核心,在項(xiàng)目開發(fā)過程中,其實(shí)很少使用抽象類,接口用得比...
摘要:前言最近將公司項(xiàng)目的從版本升到了版本,跟完全不兼容,是一次徹底的重寫。升級過程中踩了不少的坑,也有一些值得分享的點(diǎn)。沒有就會(huì)匹配所有路由最后不得不說升級很困難,坑也很多。 前言 最近將公司項(xiàng)目的 react-router 從 v3 版本升到了 v4 版本,react-router v4 跟 v3 完全不兼容,是一次徹底的重寫。這也給升級造成了極大的困難,與其說升級不如說是對 route...
摘要:死亡狀態(tài)有兩個(gè)原因會(huì)導(dǎo)致線程死亡方法正常退出而自然死亡。一個(gè)未捕獲的異常終止了方法而使線程猝死。注意,放入的線程不必?fù)?dān)心其結(jié)束,超過不活動(dòng),其會(huì)自動(dòng)被終止。線程間相互干擾描述了當(dāng)多個(gè)線程訪問共享數(shù)據(jù)時(shí)可能出現(xiàn)的錯(cuò)誤。 線程 進(jìn)程與線程的區(qū)別 線程是指進(jìn)程內(nèi)的一個(gè)執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實(shí)體。一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程。 線程的五大狀態(tài) 新建狀態(tài)(New):例如...
摘要:以上的描述說,此方法有兩個(gè)參數(shù),新創(chuàng)建對象的原型對象。創(chuàng)建一個(gè)干凈的對象,我們就要借助上面的這個(gè)方法了是基本數(shù)據(jù)類型,是沒有原型的,所以講作為第一個(gè)參數(shù)傳入創(chuàng)建出來的對象就是干凈的對象。這個(gè)對象不會(huì)繼承任何。 什么叫干凈的map 一般聲明一個(gè)map對象我們使用字面量的方法 let map = {}; 我們知道,使用字面量聲明的對象其實(shí)就是默認(rèn)繼承了Object對象,也就是說這個(gè)對象擁有...
閱讀 1715·2021-09-08 10:42
閱讀 3671·2021-08-11 10:23
閱讀 4181·2019-08-30 14:10
閱讀 2794·2019-08-29 17:29
閱讀 3154·2019-08-29 12:50
閱讀 695·2019-08-26 13:36
閱讀 3521·2019-08-26 11:59
閱讀 1548·2019-08-23 16:23