// 產生一個 function object, 會輸出「我是 ooo」
function say() { print('I am ' + this) }
// 產生一個 function object, 拿這當 Duck 的 prototype
function Duck() { }
// 讓 Duck prototype 產生一個成員,也就是讓 say 變成他的 method
Duck.prototype.say = say;
// 定義 toString 讓 say 使用
Duck.prototype.toString = function(){ return 'Duck' }
// 假設現在有一個讓某東西說話的 function
function say_hello(who){ who.say() }
// 於是我們可以這樣呼叫 say_hello
say_hello(new Duck)
在如此的語意中,"new Duck" 意味著 ECMAscript 得先去尋找 Duck 的 prototype,然後 clone 一份該 prototype 後傳回物件的 instance,所以 function say_hello(who) 的 "who" 被帶入一份 Duck 的複製,也因此,執行 say 則會輸出:I am Duck而回到 Javascript 的物件導向設計,其 prototype inheritance 的特性落實於 this, new, prototype 等關鍵字的使用,再巧妙地摻入 lexical scope (execution context 和 scope chain)、匿名函數、function object 等 functional programming 特性,組合表現出物件導向的多個面向。在 [石頭閒語] 有若干篇值得一讀的好文,與此主題相關者可參見: 鋪陳許久,本文終於能切入主題了,是的,掌握 prototype-base 的思維,一句話來說就是:
#include <stdio.h> #include <stdlib.h> struct _rect { int x, y; int (**prototype)(struct _rect *); }; typedef struct _rect Rect; typedef int (*Rect_method)(Rect *); /**< method enumeration */ enum { GET_X, GET_Y, END_OF_NAME_TABLE }; /**< name table */ Rect_method *rect_prototype; /**< method as an array of prototypes */ /* constructor & destructor */ Rect *rect_new(int x, int y) { Rect *p = (Rect *) malloc(sizeof(Rect)); p->x = x, p->y = y; p->prototype = rect_prototype; return p; } void rect_delete(Rect *p) { free(p); } /* methods: getter */ int rect_get_x(Rect *p) { return p->x; } int rect_get_y(Rect *p) { return p->y; } /* register prototype */ void rect_init_prototype(void) { rect_prototype = (Rect_method *) malloc((sizeof(Rect_method)) * END_OF_NAME_TABLE); rect_prototype[GET_X] = rect_get_x; rect_prototype[GET_Y] = rect_get_y; } /* deregister prototype */ void rect_delete_prototype(void) { free(rect_prototype); } static void test_suite(void) { Rect *r1 = rect_new(1, 2); Rect *r2 = rect_new(3, 4); printf("r1 = (%d, %d), r2 = (%d, %d)\n", r1->prototype[GET_X](r1), r1->prototype[GET_Y](r1), r2->prototype[GET_X](r2), r2->prototype[GET_Y](r2)); rect_delete(r1); rect_delete(r2); } int main(void) { rect_init_prototype(); test_suite(); rect_delete_prototype(); return 0; }試著編譯並執行:
$ gcc -o js-prototype{,.c} && ./js-prototype
r1 = (1, 2), r2 = (3, 4)
顯然,我們的 prototype 操作已發揮功能,當然,這僅是一個模擬的手法,但可從中窺見 Javascript 在此機制的特性。呵,這讓我想到一年半前,曾經在 ptt CSSE 板看過 semop 示範一些由 C 實作動態 OO 的機制。
不過一來我 C 不熟,二來這段時間我自己本身的改變也滿大的。總之大概看過去之後,
多少就比較能想像由 C 實作一個完整的 OO 系統要怎麼做。或許也像是在設計一個新語言吧?
那篇文章在:
http://www.ptt.cc/bbs/CSSE/M.1167950648.A.894.html
或:
● 1461 1/05 semop R: [討論] 念完資工之後...
┌─────────────────────────────────────┐
│ 文章代碼(AID): #15dOCuYK (CSSE) [ptt.cc] Re: [討論] 念完資工之後... │
│ 這一篇文章值 663 銀 │
└─────────────────────────────────────┘
Hi Jserv
I am finding a way to parse and run "javascript" by python.
Only python can run on google app engine. so I try to write a python app to parse and run "javascript".
由 Hugo Darwin 發表於 August 19, 2008 05:47 PMHi Jserv,
both mozilla and firefox use a javascript interpreter
'spidermonkey'. You can study and give us some tutorial.