1. 程式人生 > 其它 >[軟體構造] reading 2: basic typescript

[軟體構造] reading 2: basic typescript

reading 2: basic typescript

http://web.mit.edu/6.031/www/fa21/classes/02-basic-typescript/

快照圖,同一語句有多種詳細程度的表現形式,根據要求靈活選擇。

雙圈箭頭表示此變數是const, 雙圈物件表示此物件是immutable。

 

變數s 被定義為string型別,其值為"abc"。實際這是定義了一個變數s,s指向一個string物件"abc",這個"abc"物件是immutable的,也就是說這個物件永遠是"abc",其內容不能改變。

s.concat("123")呼叫了string物件中的concat方法,這個方法建立了一個新字串("abc123"),並且返回這個字串。但是,之前已有的字串"abc"不會被這個concat方法的呼叫影響到,因為string是immutable的。

而且,由於並沒有一個變數來接收concat方法的返回值,此方法新建立的字串"abc123",在被建立後就被丟棄了。

綜上,s.concat("123") 語句沒有改變變數s 或 "abc"物件的內容。(變數s的內容可以看作它指向的東西,它指向哪裡沒有變,指向的物件"abc"本身也沒有變。)

 

reassigning a parameter inside a method does not reassign a variable in the caller. Here, reassigning n does not reassign i. The only way to communicate back to the caller through a parameter is to mutate the object that the parameter points to.

關於call-by-value的閱讀材料:

This kind of parameter-passing behavior is referred to as call-by-value, because the parameter receives an initial value from the caller, but then the parameter can be freely reassigned without affecting the caller. Most programming languages, not only TypeScript/JavaScript but also Python, Java, and C, use exclusively call-by-value. A few languages, notably C++ and C#, also offer

call-by-reference semantics, where the parameter n could become an alias for the passed-in variable i, so that reassigning n also reassigns i. But this is unusual; call-by-value is by far the norm.

我的解析:執行f前,為:

t:"a"

tarr:["a"]

執行f後,由於是按值呼叫,t、tarr不變。

t:"a"

tarr:["a"] // 錯誤原因是簡單地認為按值呼叫就是開一個副本,原來的資料和副本互不相通,對副本的操作完全不影響。沒有深刻理解immutable和mutable帶來的差異。

答案:

解析:

初始化:

Let’s run through the execution of this larger example, using snapshot diagrams to visualize what’s going on. It’s good to form pictures like this in your head when you’re mentally executing code.

let t:string = "a" declares a new variable t that points to a string object "a". This object is immutable, it will always represent the character sequence "a".

let tarr:Array<string> = [t] declares a new variable tarr that points to a new array value, whose first element points to the current value of t, specifically "a". This array object is mutable, so it might change its value internally when methods are later called on it.

f函式:

f(t, tarr) calls the function f and instantiates new parameter variables s and arr pointing to the string and array object values that we passed, respectively. Now we enter the body of f.

s.concat("b") calls the concatmethod on the string object. As in the 1st exercise in this sequence, the method creates a fresh string object for "ab" and returns it, but that return value is not assigned to anything, and the new object is discarded. Strings are immutable, so the existing string "a" cannot be affected by this method call, and this statement has no effect on any of the existing variables or objects.

注意這裡按值呼叫的實質:並不是建立一個變數和一個新的物件(和原來物件值相同),而是建立一個新的變數,指向原來那個物件。其實這裡的“按值呼叫”更類似於C語言中的傳遞地址+寫許可權的有無:新建一個指標,指向原來的地址,通過設定屬性為immutable或mutable來決定寫許可權的有無。若無寫許可權,則在別處開闢一塊新空間,寫入新的資料;若有寫許可權,則直接修改相應地址處的資料。

總結:如果指向的物件是immutable,那麼在呼叫到可能會修改物件值的方法時,保留原來的物件不變,建立一個新的經方法修改後的物件,並讓原來的變數指向這個新的物件。而如果是mutable,在碰到可能會修改物件值的方法時,會直接修改這個物件。

s+="c":

s += "c" implicitly calls concat to produce a fresh string object with "ac", and then assigns it to s. The variable t is not affected by this assignment.

由於string是immutable,s+="c"時,呼叫到可能會修改物件值的方法時,保留原來的物件不變,建立一個新的經方法修改後的物件,並讓原來的變數指向這個新的物件。

arr.push("d"):

arr.push("d") calls the push method on the array object, and as we saw in the previous section, this method mutates the array object to add a new element "d". The variabletarris affected by this assignment, because it points to the object that was mutated.

Now we return from the method call, and examine the values of t and tarr, to find that t still points to the original string "a", while tarr points to the original array object, whose contents are now ["a","d"].

As in the 2nd exercise in this sequence, reassigning a parameter inside a method does not reassign a variable in the caller. Here, reassigning s does not reassign t. But we can mutate the object that the parameter points to, and that is how arr affected tarr.

由於Array是mutable,在arr.push("d")時,會直接修改這個物件。

迭代時,加const,防止在迴圈體執行過程中迴圈變數的值被不小心改變了。