data: 2017-8-13 22:07:36
title: 談一談編程系列之一
最近看不同語言的基礎比較多,前一段時間又補了幾本底層的書,總歸有想寫點什么的沖動,于是開了一個系列,《談一談編程》,這里是系列之一。
初衷:計算機是以純粹人類理性構建起來的學科。
this
關于 this
的探討來自 ES6 的 arrow function
(箭頭函數),先看代碼:
// 將數組中的每個數 ×2
const double = nums.map(function(num){
console.log(this); // window
retrun num*2;
});
const double = nums.map((num) => num*2); // parent
前一種寫法,this
指向當前回調函數,而回調函數,屬于當前 window
,所以這里的 this
實際上指向的是 window
;
后一種寫法是 ES6 新增的箭頭函數,this
指向自己的父類。
所以,這個看起來像「語法糖」的改動,其實并不是簡單的將 function(){}
這種格式給簡化了,有興趣可以用 babel
幫你翻譯成以前的版本試試。
當然,還沒完,再看看:
<?php
class Test
{
private $a;
public function getA()
{
return $this->a;
}
}
有點 hello world
的既視感,是的,這個確實很簡單,但是這個就是為了說明 this
的本質:當前實例化的類。把這個本質再套到上面去看看。
賦值、引用、拷貝
先不談淺拷貝、深拷貝、寫時拷貝這些更深一層的概念,還是先看簡單代碼:
a = b = 1
a = 2
print(a, b) # a b 不同
a= b = [1,2,3]
a[0] = 4
print(a, b) # a b 相同
直接說一下結論:賦值生成引用。引用?引用 == 指針?但是這里沒有用 &
符號呀。所以,這里要好好說道一下 a = 1
這個賦值語句了:
- 分配內存給 1 這個數
- 分配內存給變量 a
-
=
號其實建立的是 a 到 1 的聯系(引用)
繼續說本質:既要給變量分配內存,也要給數據分配內存,還要給二者建立起聯系。好好對比一下這個例子,順便可以試試下面這個:
import sys
sys.getrefcount(1) # 引用計數:98
我們還沒寫具體代碼,1 這個數據的引用計數就有 98 個。
關于引用計數這個再啰嗦:
- 動態語言有 gc(垃圾回收)機制的,其中一個實現就是把引用計數為 0 的數據清理掉;
- 引用要形成環了怎么辦?(這個可以參考 php5.4 的更新內容,里面就有這方面的優化)。
聊完了引用,問題也就出來了,有時我們就是需要一份一樣的數據,然后兩份數據不要相互影響。當然可以,內存中復制一遍,這就是拷貝了。
比較一下兩者的本質,一個只需要建立一下聯系,一個卻要分配內存并寫入數據,開銷 不一樣。所以,會出現這樣一個關鍵字:clone
。同時也想指出,類的創建和銷毀需要很大的開銷的。
再回到一開始列的幾個概念,本質其實是:建立緩沖,削弱拷貝帶來的開銷。這里講講「寫時拷貝」。
如果接觸過「高性能服務器開發」或者看過《現代計算機操作系統》,這個詞就不會陌生了,操作系統的慣用套路。其實就是一種 延時 機制,數據到需要 寫 的時候才 復制,不到這一刻,就沒必要提前付出代價。
小結
只是想 拋磚引玉 一下,基本都是飄過,得到知識是一個漸進與構建的過程。
暢銷書往往會夸大,只是到最后,你還是發現你需要那些大部頭。