2015-08-16 134 views
1

我想重新排列我的代碼到面向對象,但我無法找出我的錯誤在這裏,尤其是因爲它們根據不同的教程和示例顯示正確。 我想我誤解了JS的對象實例化和調用堆棧。Javascript面向對象和類問題

我會提供一些我不明白的例子。

我想在這裏做的是對數組做一些操作,然後把它拿到另一個類。

https://jsfiddle.net/8g22nj8y/1/

<script> 
$(document).ready(function() { 
    var p = new Parser(); 
    p.init(); 
    p.getArray(); 
    p.getArray2(); 
    p.get3(); 
}</script> 

function Parser() { 

var myArray = []; 
this.myArray2 = []; 
thisReference = this; 
    this.myArray3=[]; 

return { 
    init: function() { 
     alert("huhu"); 
     this.parse2(); 
     parse(); 
    }, 
    getArray: function() { 
     alert(thisReference.myArray2.length); 

    }, 
    getArray2: function() { 
     alert(myArray); 
    } 
} 

function parse() { 
    var arr = [1, 2, 3]; 
    myArray.push(arr); 
    myArray2.push(arr); 

for(var i =0;i<10;i++){ 
     a=[]; 
     a.push(i); 
     thisReference.myArray3.push(a); 
    } 

}}Parser.prototype.parse2 = function() { 
var arr = [1, 2, 3]; 
myArray.push(arr); 
this.myArray2.push(arr);}; 

獨立我如何運行它,它總是說this.parse2()不是一個函數。 當我只使用parse()時,它說myArray2是未定義的,儘管它顯然存在 - 就像「類變量」一樣。如果我將parse()中的myArray2更改爲thisReference.myArray2,它可以工作。

爲什麼?我認爲解析()明確的內部函數能夠獲取外部函數中的所有變量 - 在本例中爲Parser()。當我現在使用myArray3時,如果它與thisReference一起使用或者與此一起使用。 「它沒有被定義」。 如果我使用thisReference調用parse2它工作,但然後「myArray沒有定義」,是它是一個局部變量,但它在同一個類中,如果我調用parse()我可以使用它沒有問題。

此外:

簡化:https://jsfiddle.net/Lzaudhxw/1/

function Syntax(){ 
    var mine = new Lex(); 
    myRef=this; 
    } 
    Class1.prototype.foo=function(){ 
     myRef.mine.setFunc(5); 
     myRef.mine.publicFunc();} 


function Lex(){ 
    this.x, this.h=1; 
    return{ 
     publicFunc: function(param){ 
     this.h; 
     this.x; 
     }, 
     setFunc: function(x){ 
     this.x=x; 
     } 
} 

最初我集合H爲1。如果現在instantiiate語法,並從該從萊克斯的publicFunc都是未定義的呼叫。但是,如果我從語法中運行foo()並再次調用publicFunc,則將x設置爲該值,並且h未定義。爲什麼不可能預先定義一個可變的(在這種情況下是h),然後使用它?

編輯到Jan's答:

我看了很多教程,您應該存儲「這種」爲變量的一些生產代碼。爲什麼myRef指向語法對象以外的其他東西? :O 爲什麼myRef不是語法的變量?它是否必須是this.myRef? 啊,對,var表示本地,所以我的構造函數只能訪問?!

我不想初始化「x」,只定義它。 Ahh with return {}我正在創建一個新的類/對象,然後很清楚這一點。並沒有指出上述的變數。但要介紹一個myRef =這應該可以完成這項工作,對吧?

...那麼,使用原型來添加函數而不是內部函數會更明智嗎?

+0

作爲一個側面說明,你在技術上做的「功能性」節目。沒關係。你正在提高你的代碼能力,結果你會得到更好的代碼。 Javascript是原型的,不支持面向對象的編程。然而,許多程序員對術語背後的理論漠不關心,當他們將代碼劃分爲對象,使用函數和所有爵士時,將它稱爲面向對象。面向對象的概念:http://www.c4learn.com/cplusplus/cpp-pillars-of-oop/ OOP對你來說依然重要,因爲它是考慮問題的好方法。 –

+0

@PaluMacil Javascript基本上是面向對象的,只是與例如C變體不一樣。 Javascript只是做非常非常不同的事情。正因爲如此,您不應該像編寫C變體應用程序那樣編程,而應該使用Javascript的優點(您提到的OOP和函數編程的組合)。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript – Jan

+0

可能會有一小部分人會同意你的觀點(我這樣說是因爲維基百科似乎強烈地表示它是OO) ,但爲了使用繼承,你犧牲封裝(偉大的答案覆蓋了這裏:http://stackoverflow.com/questions/107464/is-javascript-object-oriented),對我來說這是公然違反面向對象的基本定義。這不是語言缺陷。 JavaScript的工作方式並不遜色,但我確實認爲人們應該認識到原型是不同的,否則當他們學習Python,C#或PHP時,他們會編寫可憐的OO代碼。 –

回答

2

是的,你有一堆JS概念錯誤。我建議你閱讀文檔。試着添加一些解釋。

function Syntax(){ 
    // Since you're returning a new object from "Lex" straight away, there's 
    // little point of using "new" here 
    var mine = new Lex(); 
    // Why store "this" here? "this" will be accessible from your prototype 
    // methods pointing to your object instance... Provided you use "new Syntax()", 
    // Otherwise "myRef" will (probably) point to the global object. 
    myRef=this; 
} 

// Where's "Class1"? You don't have a Class1 function anywhere. You probably mean "Syntax" 
Class1.prototype.foo=function() { 
    // "myRef" is not a property of "Syntax", so it wouldn't be accessible here. 
    // Furthermore, "mine" is declared as a variable above, so it wouldn't be 
    // accessible in this manner even if "myRef" pointed to "this" (which it doesn't). 
    myRef.mine.setFunc(5); 
    myRef.mine.publicFunc(); 
} 

function Lex(){ 
    // This is a correct property declaration of h. You're not setting the 
    // value of x here though, just calling it. Javascript allows "trying" 
    // to call ANY property of ANY object without giving neither a compilation 
    // nor runtime error, so calling the undefined "this.x" here is valid. 
    // It just won't do anything. 
    this.x, this.h=1; 
    // Here you return a new object straight off, so the below "this" will point 
    // to the object below, not the "Lex" object defined above. So your above 
    // defined "this.h" will not be used, it's a property of a different object. 
    return { 
     publicFunc: function(param){ 
      this.h; 
      this.x; 
     }, 
     setFunc: function(x){ 
      this.x=x; 
     } 
    } 
// You're missing a closing bracket here. 

什麼你可能嘗試做會看起來像這樣用正確的JavaScript語法

function Syntax(){ 
 
    this.mine = Lex(); 
 
} 
 
Syntax.prototype.foo=function() { 
 
    this.mine.setFunc(5); 
 
    this.mine.publicFunc(); 
 
} 
 

 
function Lex() { 
 
    return { 
 
     h:1, 
 
     publicFunc: function(){ 
 
      console.log(this.h); 
 
      console.log(this.x); 
 
     }, 
 
     setFunc: function(x){ 
 
      this.x=x; 
 
     } 
 
    } 
 
} 
 

 
var s = new Syntax(); 
 
s.foo();

但是從Lex返回一個對象將在大多數情況下非常不切實際。所以,你真的真的想要做的可能是

function Syntax(){ 
 
    this.mine = new Lex(); 
 
} 
 
Syntax.prototype.foo = function() { 
 
    this.mine.setFunc(5); 
 
    this.mine.publicFunc(); 
 
} 
 

 
function Lex() { 
 
    this.h = 1; 
 
} 
 
Lex.prototype = { 
 
    publicFunc: function(){ 
 
     console.log(this.h); 
 
     console.log(this.x); 
 
    }, 
 
    setFunc: function(x){ 
 
     this.x=x; 
 
    } 
 
}; 
 

 
var s = new Syntax(); 
 
s.foo();

+0

感謝您的詳細解答。我已經閱讀了很多文檔,但在JS中我只能理解一些東西......而且我還有一些問題需要回答。 – user3320354

+0

@ user3320354如果您有更多問題,請提出一個新問題。隨意指點我的方向,我可以看看。如果您使用搜索,最可能的是,您的問題已經在SO上有答案。另外,當你說「許多文件」時,我想知道你是否明白我的意思。您是否閱讀過所有MDN和EcmaScript 5和6,或者您認爲「很多」是什麼意思?請參閱我發佈的關於您的問題的註釋的鏈接,並注意這些都只是*相同*文檔的*部分*,並且只是提示如何開始*閱讀MDN文檔。 – Jan

+0

其實沒有那麼多的問題(但你仍然不應該用新的問題來編輯你的問題,它已經被回答了)。 *「var表示本地,所以我只能在構造函數中訪問!」*是的。 *「我不想初始化」x「,只定義它」*正如我所說的,您不需要「定義」對象屬性。你可以嘗試調用任何屬性,並且JS不會失敗,它只會返回值'undefined'。如果您希望它不返回undefined,請設置其值。 *「因此,使用原型來添加函數而不是內部函數會更明智嗎?」*取決於。你應該查看差異。 – Jan