国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

淺析JavaScript原型繼承的陷阱

2019-11-20 21:32:02
字體:
來源:轉載
供稿:網友

JavaScript默認采用原型繼承。雖然沒有類(class)的概念,它的函數(function)可以充當構造器(constructor)。構造器結合this,new可以構建出類似Java的類。因此,JavaScript通過擴展自身能模擬類式(class-based)繼承。

JavaScript和其它面向對象語言一樣,對象類型采用引用方式。持有對象的變量只是一個地址,而基本類型數據是值。當原型上存儲對象時,就可能有一些陷阱。

先看第一個例子

復制代碼 代碼如下:

var create = function() {
    function Fn() {}
    return function(parent) {
        Fn.prototype = parent
        return new Fn
    }
}()

var parent = {
    name: 'jack',
    age: 30,
    isMarried: false
}
var child = create(parent)
console.log(child)

create工具函數實現了一個基本的原型繼承,每次調用create都會根據parent對象去復制一個新對象,新對象全部的屬性都來自于parent。這里parent有三個屬性,都是基本數據類型:字符串,數字,布爾。

這時修改child看看會不會影響parent

復制代碼 代碼如下:

child.name = 'lily'
child.age = 20,
child.isMarried = true

console.log(child)
console.log(parent)

結果如下

即修改child不會影響到parent。

再看看另外一個例子

復制代碼 代碼如下:

var create = function() {
    function Fn() {}
    return function(parent) {
        Fn.prototype = parent
        return new Fn
    }
}()

var parent = {
    data: {
        name: 'jack',
        age: 30,
        isMarried: false
    },
    language: ['Java']
}
var child = create(parent)

child.data.name = 'lily'
child.data.age = 20
child.data.isMarried = true
child.language.push('javascript')
console.dir(child)
console.dir(parent)

注意這里的parent的兩個屬性data,language都是引用類型,一個是對象,一個是數組。child仍然繼承與parent,隨后修改了child,結果如下

可以看到,此時parent也被修改了,和child的name,age等都一樣了。這是使用原型繼承時需要注意的。

使用繼承時比較好的方式是:

1,數據屬性采用類式繼承(掛在this上),這樣new時也可以通過參數配置

2,方法采用原型繼承,這樣能節省內存,同時子類重寫方法也不會影響父類

下面是一個滿足以上2點的寫類工具函數

復制代碼 代碼如下:

/**
 * @param {String} className
 * @param {String/Function} superCls
 * @param {Function} factory
 */
function $class(name, superClass, factory) {
    if (superClass === '') superClass = Object
    function clazz() {
        if (typeof this.init === 'function') {
            this.init.apply(this, arguments)
        }
    }
    var p = clazz.prototype = new superCls
    clazz.prototype.constructor = clazz
    clazz.prototype.className = className
    var supr = superCls.prototype
    window[className] = clazz
    factory.call(p, supr)
}

對象類型放在父類原型上時務必小心子類修改其,這時繼承于該父類的所有子類的實例都將被修改。而這造成的bug很不容易發現。

ES5中加入了一個新API用來實現原型繼承:Object.create。可以用它替代上面自實現的create函數,如下

復制代碼 代碼如下:

var parent = {
    name: 'jack',
    age: 30,
    isMarried: false
}
var child = Object.create(parent)
console.log(child)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 达日县| 乳山市| 扎兰屯市| 攀枝花市| 正蓝旗| 天峨县| 那坡县| 疏勒县| 重庆市| 汶川县| 木里| 汾西县| 安远县| 津南区| 朔州市| 昆明市| 梧州市| 京山县| 卓尼县| 定结县| 吉安市| 峨山| 凭祥市| 阿拉善右旗| 开化县| 北川| 灌云县| 鲁甸县| 河北省| 琼结县| 永顺县| 湘潭县| 抚州市| 上饶市| 乌兰县| 利川市| 桐庐县| 连江县| 龙江县| 洪江市| 佛坪县|