摘要:面向對象原型面向對象想開一個車,你不需要自己去造一個車,只需要一把鑰匙,車對于你來說就是一個對象。使用構造函數模式和原型模式組合初學筆記,個人記錄備忘,如有謬誤,歡迎指正。
面向對象、原型 面向對象
想開一個車,你不需要自己去造一個車,只需要一把鑰匙,車對于你來說就是一個"對象"。
在JavaScript中的"對象", 具有屬性,當屬性的值是一個函數時,那么此屬性就是這個對象的方法.訪問屬性的方式參考Object介紹
首先想到的是字面量創建對象,其次是創建一個對象實例,然后一次對對象屬性進行賦值.但是無論這兩種那個方法都有個缺點,當需要重復創建大量相同的對象時,產生大量代碼這是很不理想的,這時想到函數的一個功能就是講重復代碼進行簡化,以便多次使用,那么構造函數形式創建多個對象方式就是理想的選擇了.
什么是構造函數?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) // 分別調用
這里有幾點需要注意,首先是這個this是誰? new操作符有什么作用?
this指向的創建的實例,這里指的是 person2, 而new操作符可以創建一個對象實例.
使用new通過構造函數方式創建對象的實際包含的步驟有:創建一個新對象,
將構造函數的作用域賦給新對象,此時this已經指向新對象,操作this等同操作新對象
執行構造函數里的代碼
返回創建的新對象
如何檢測對象的類型? (檢測操作符右邊的函數原型是否存在于左邊的實例的原型鏈上)使用instanceof 操作符,返回布爾值.
p1 instanceof Person; p1 instanceof Object;
第二個檢測,無論是自己創建的構造函數對象還是字面量對象,均為true,因為他們均繼承自Object. 對于某個構造函數創建的實例當其構造函數的原型被改變后使用此操作符發現返回false ,原因在于在實例的原型鏈上構造函數的原型是舊的對象,不是新的對象,自然也就不對了。instanceof-MDN
那么對于構造函數創建的對象里的方法,每次創建實例時都要重新創建,如何解決?思路是將這個方法提到實例的外面去,如果是全局對象不就可以直接調用了嗎?可是全局函數對于封裝來說可沒好處,所以原型模式也就有了用處.
原型原型是定義能夠被對象實例所使用的屬性和函數的一種方式.原型的屬性會變成實例的屬性.
這段話不容易理解.一點點分析,對象的原型屬性(prototype)指向的是一個對象,對象里存的屬性和方法在對象實例后(即構造函數方法創建的新對象) 可以被實例對象訪問使用.
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"
在函數創建的時候,prototype屬性就被創建出來了,通過構造函數生成的實例在瀏覽器下支持一個屬性__proto__ 查看prototype(原型里的對象)
如圖所示
顯示的是當一個實例在自己屬性中找不到相應的方法或者屬性時往上一層尋找的情況。
檢測某個屬性屬于實例還是原型:
person1.hasOwnProperty("name") 當這個屬性是實例的返回true,是原型的返回false
注意到在實例中重寫某個屬性會阻止訪問原型中的這個屬性,可是不會影響到原型中的屬性。
多帶帶操作的in操作符
使用這個操作符可以檢測某個屬性是否可以通過對象訪問,這也就指的是無論這個屬性是實例中的還是原型中的,要知道實例可以通過 __proto__ 訪問,由上圖可知
"name" in Person1 可以訪問返回true,否則返回false
這個操作符可以和上面的hasOwnperty() 結合使用判斷某個屬性是否存在且存在于哪里。
如何為原型添加屬性和方法?由上面介紹可知,通過Person.prototype.name = "kangkang"
這種方法甚是繁瑣,多個屬性、方法將會導致反復的輸入,所以對象字面量的書寫方式就能很好解決這個問題。
function Person () { } Person.prototype = { name : "Kangkang", age: 20, job: "student", sayName = function() { console.log(name) } }防止實例與原型的鏈斷開
謹慎在初始化原型后再將其改變為另外一個對象
function Person () { } var friend = new Person() Person.prototype.sayHi = function() { console.log("hi") } friend.sayHI(); // 在創建對象后再對原型添加方法依然有效
下面這種情況:
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
這種情況相當于在原型初始化后又重新生成對象并且賦值,而原來的實例是指向初始化時的對象地址,故無法訪問新的原型里的屬性和方法.
原型對象和屬性的區別?如下程序:
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)
由上面的代碼得出:
當對原型中基本類型值屬性和方法在實例中重新添加會阻止尋找到原型中的屬性和方法,當用delete 操作符刪除后依然可以找到原型中的屬性和方法,也就是說在實例中重定義這兩種情況不會影響原型中的屬性和方法,但是如果原型中的屬性對應的值是引用類型,由于引用類型的特性,實例得到了相同的這個屬性的地址,又由于原型是實例公用的方法,所以當任一實例操作這個引用值屬性時都會影響到其他這個對象的實例。所以組合使用構造函數和原型也就很好解決這個問題。
使用構造函數模式和原型模式組合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
初學筆記,個人記錄備忘,如有謬誤,歡迎指正。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94358.html
摘要:抽象類和接口小記抽象類和接口實現了的多態多態是面向對象程序語言的核心在項目開發過程中其實很少使用抽象類接口用得比較多今天小記一下抽象類和接口的區別抽象類抽象類不能被實例化抽象類可以繼承可以定義變量可以定義構造方法抽象方法的要顯式的寫出來其子 Java抽象類和接口小記 Java抽象類和接口實現了java的多態.多態是面向對象程序語言的核心,在項目開發過程中,其實很少使用抽象類,接口用得比...
摘要:前言最近將公司項目的從版本升到了版本,跟完全不兼容,是一次徹底的重寫。升級過程中踩了不少的坑,也有一些值得分享的點。沒有就會匹配所有路由最后不得不說升級很困難,坑也很多。 前言 最近將公司項目的 react-router 從 v3 版本升到了 v4 版本,react-router v4 跟 v3 完全不兼容,是一次徹底的重寫。這也給升級造成了極大的困難,與其說升級不如說是對 route...
摘要:以上的描述說,此方法有兩個參數,新創建對象的原型對象。創建一個干凈的對象,我們就要借助上面的這個方法了是基本數據類型,是沒有原型的,所以講作為第一個參數傳入創建出來的對象就是干凈的對象。這個對象不會繼承任何。 什么叫干凈的map 一般聲明一個map對象我們使用字面量的方法 let map = {}; 我們知道,使用字面量聲明的對象其實就是默認繼承了Object對象,也就是說這個對象擁有...
閱讀 1618·2021-09-08 10:42
閱讀 3604·2021-08-11 10:23
閱讀 3959·2019-08-30 14:10
閱讀 2732·2019-08-29 17:29
閱讀 3090·2019-08-29 12:50
閱讀 637·2019-08-26 13:36
閱讀 3456·2019-08-26 11:59
閱讀 1487·2019-08-23 16:23