成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

談?wù)?javascript 面向?qū)ο蟮囊恍┘毠?jié)問題

newsning / 3346人閱讀

摘要:同時,創(chuàng)建的子類有幾個固定字段,分別是初始化函數(shù)原型初始化函數(shù)對象通過這個函數(shù),把基類和子類的函數(shù)合并執(zhí)行,這樣解決了基類構(gòu)造函數(shù)無法執(zhí)行的問題。二是構(gòu)造函數(shù)可能不止會操作,還可能會修改全局的某些狀態(tài)比如計數(shù)器。

綜述

在 ES6 之前,ES5 實現(xiàn)面向?qū)ο笫谴蠹医?jīng)常討論的問題,趁著 ES6 還沒進入瀏覽器,借我自己的一段腳本,跟大家討論一下 js 面向?qū)ο蟮囊恍┘毠?jié)問題,歡迎留言指教。

例子代碼

基本的概念比如“基類”,“子類”等就不解釋了。下面是我寫的一段實現(xiàn)類繼承的 js 腳本:

/**
 * @file Inheritable.js
 * @author Y3G
 * @fileoverview
 * 可繼承對象
 */

var _ = require("lodash");
var assert = require("./assert");
var seq = require("./seq");

/**
 * 并聯(lián)函數(shù)
 * @return 生成的函數(shù)
 */
var parallel = function () {
    var fns = _.filter(arguments, _.isFunction);

    if (fns.length === 0) return;

    return function () {
        _.forEach(fns, function (fn) {
            fn.apply(this, _.slice(arguments));
        });
    };
}

/**
 * 創(chuàng)建類
 * @param base 基類函數(shù)或原型對象
 * @param ex 實例擴展
 * @return 生成的類函數(shù)
 *         默認(rèn)方法:
 *           __init__: 構(gòu)造函數(shù)
 *           __initProto__: 原型構(gòu)造函數(shù)
 *         默認(rèn)類方法:
 *           makeClass: 創(chuàng)建類
 *           makeSubClass: 創(chuàng)建子類
 */
function makeClass(base, ex) {
    base = base || {};
    ex = ex || {};

    var proto = _.isFunction(base) ? new base(true) : base;

    ex.__init__ = parallel(proto.__init__, ex.__init__); // 實例初始化函數(shù)
    ex.__initProto__ = parallel(proto.__initProto__, ex.__initProto__); // 原型初始化函數(shù)
    proto = _.mixin(proto, ex); // 合并原型和實例擴展

    function SubClass(isProto) {
        var initFunc = isProto ? this.__initProto__ : this.__init__;
        if (_.isFunction(initFunc)) {
            initFunc.apply(this, _.slice(arguments));
        }
        
        this.$id = seq();
    }

    if (_.isFunction(base)) {
        // 復(fù)制靜態(tài)函數(shù)等屬性到子類
        _.forOwn(base, function (val, key) {
            SubClass[key] = val;
        });
    }

    SubClass.prototype = proto;
    SubClass.prototype.constructor = SubClass;
    SubClass.makeSubClass = _.curry(makeClass, SubClass);
    SubClass.makeClass = makeClass;

    return SubClass;
}

/**
 * 根基類
 * @class Root
 */
var Root = makeClass();

module.exports = Root;

這段代碼導(dǎo)出了一個根基類 Root,它有一個靜態(tài)方法叫做 makeSubClass,調(diào)用可生成一個 Root 的子類,創(chuàng)建出的子類同樣帶有 makeSubClass 這個靜態(tài)方法。同時,創(chuàng)建的子類有幾個固定字段,分別是:

__init__ 初始化函數(shù)

__initProto__ 原型初始化函數(shù)

$id 對象 id

通過 parallel 這個函數(shù),makeClass 把基類和子類的 __init__ 函數(shù)合并執(zhí)行,這樣解決了基類構(gòu)造函數(shù)無法執(zhí)行的問題。

下面說說我對幾個細節(jié)問題的思考。

幾個問題和我的看法

:構(gòu)造函數(shù) __init__ 的執(zhí)行順序是基類 -> 子類比較好還是子類 -> 基類比較好?

按照我貼的代碼,是基類的構(gòu)造函數(shù)先執(zhí)行,當(dāng)時我是想模仿 C++。但是我現(xiàn)在認(rèn)為應(yīng)該子類構(gòu)造函數(shù)先執(zhí)行。

原因很簡單,就是 ES6 使用的是類 java 方式, constructor 函數(shù)是子類先執(zhí)行的,并且基類 constructor 是靠
super() 手工調(diào)用的?;谝稽c java 的使用經(jīng)驗,我也認(rèn)為這樣的構(gòu)造順序,比基類 -> 子類靈活不少。另外,采用和 ES6 一樣的構(gòu)造順序,更有利于移植。

__initProto__ 是什么鬼?

這是我一直以來堅持的看法——用 js 模擬類,如果一個類的實例有可能作為 prototype 存在,就必須把實例構(gòu)造和 prototype
構(gòu)造分開,而 __initProto__ 就是專門用來初始化 prototype 的。

原因有兩方面:

一是對象可能會很昂貴,占很多資源。

二是構(gòu)造函數(shù) __init__ 可能不止會操作 this,還可能會修改全局的某些狀態(tài)(比如計數(shù)器)。這種時候多創(chuàng)建一個和少創(chuàng)建一個實例,顯然是不同的。

:為什么要把基類函數(shù)上的靜態(tài)內(nèi)容都拷貝到子類函數(shù)上?

因為原型鏈查找對靜態(tài)內(nèi)容無效。

比如這樣:

var Foo = Root.makeSubClass({});

Foo.SOME_STATIC_THING = 0;

var Bar = Foo.makeSubClass({});

alert(Bar.SOME_STATIC_THING);

這時候假設(shè)不拷貝 SOME_STATIC_THING 到子類上去,就不能通過 Bar.SOME_STATIC_THING 訪問到該屬性。這是非常違反常識的,沒有語言是這樣子的。同時,現(xiàn)在又有了另一個這么做的理由,就是 ES6 有 static
關(guān)鍵字,如果你使用其他方式實現(xiàn)靜態(tài)屬性,將不利于以后移植到 ES6。

不過這里有個小坑,就如果靜態(tài)變量是基本類型(比如字符串),那么顯然在子類上修改對基類無效。于是基本類型的靜態(tài)變量只能是常量,如果需要非常量的靜態(tài)變量,必須使用對象。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79802.html

相關(guān)文章

  • 談?wù)?/em>我所理解面向對象

    摘要:眾多面向?qū)ο蟮木幊趟枷腚m不盡一致,但是無論哪種面向?qū)ο缶幊陶Z言都具有以下的共通功能。原型編程以類為中心的傳統(tǒng)面向?qū)ο缶幊?,是以類為基礎(chǔ)生成新對象。而原型模式的面向?qū)ο缶幊陶Z言沒有類這樣一個概念。 什么是面向?qū)ο??這個問題往往會問到剛畢業(yè)的新手or實習(xí)生上,也是往往作為一個技術(shù)面試的開頭題。在這里我們不去談如何答(fu)好(yan)問(guo)題(qu),僅談?wù)勎宜斫獾拿嫦驅(qū)ο蟆?從歷...

    avwu 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    李昌杰 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    Lyux 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你對象”還好嗎?

    摘要:很多情況下,通常一個人類,即創(chuàng)建了一個具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    AaronYuan 評論0 收藏0
  • Java項目經(jīng)驗——程序員成長鑰匙

    摘要:當(dāng)你真正到公司里面從事了幾年開發(fā)之后,你就會同意我的說法利用找工作,需要的就是項目經(jīng)驗,項目經(jīng)驗就是理解項目開發(fā)的基本過程,理解項目的分析方法,理解項目的設(shè)計思 Java就是用來做項目的!Java的主要應(yīng)用領(lǐng)域就是企業(yè)級的項目開發(fā)!要想從事企業(yè)級的項目開發(fā),你必須掌握如下要點: 1、掌握項目開發(fā)的基本步驟 2、具備極強的面向?qū)ο蟮姆治雠c設(shè)計技巧 3、掌握用例驅(qū)動、以架構(gòu)為核心的主流開發(fā)...

    zhangfaliang 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<