原因
由于lua的弱類型動態(tài)語言的特質(zhì),克隆table的行為在lua中不說無處不在,那也是非常常見。
一般克隆table原因無外乎:
- 通過修改舊table的部分?jǐn)?shù)據(jù)創(chuàng)建新table,然后又不想由于修改新table而導(dǎo)致舊table被修改。從而保持函數(shù)的純函數(shù)性。
方法
那怎么做到呢?有如下方法:
- 直接克隆。這種方式創(chuàng)建出來的table是全新的實(shí)例,怎么修改也不會影響到原table,缺點(diǎn)是在table較大的時(shí)候創(chuàng)建耗時(shí)較久,也會占用更多內(nèi)存
function createNewTable(tb)
local newTb = clone(tb)
newTb.id = 2
return newTb
end
local tbA = {a = 1}
local tbB = createNewTable(tbA)
print(tbB.a) -- 1
print(tbB.b) -- 2
tbB.a = 3
tbB.b = 4
print(tbB.a) -- 3
print(tbB.b) -- 4
tbB.a = nil
tbB.b = nil
print(tbB.a) -- nil
print(tbB.b) -- nil
- 通過元表將新修改的數(shù)據(jù)存儲到新的table中。優(yōu)點(diǎn)是創(chuàng)建速度快,占用內(nèi)存少,修改的數(shù)據(jù)也會存儲在新的table中,不會影響到原table。缺點(diǎn)是無法將原table中的變量賦值為空,且新的table無法用pairs和ipairs遍歷到。
function createNewTable(tb)
local newTb = setmetatable({}, {__index = tb})
newTb.b = 2
return newTb
end
local tbA = {a = 1}
local tbB = createNewTable(tbA)
print(tbB.a) -- 1
print(tbB.b) -- 2
tbB.a = 3
tbB.b = 4
print(tbB.a) -- 3
print(tbB.b) -- 4
tbB.a = nil
tbB.b = nil
print(tbB.a) -- 1
print(tbB.b) -- nil
-- 只會輸出b=1, 遍歷不到tbA中的數(shù)據(jù)
for k, v in pairs(tbB) do
print(k, v)
end
克隆和元表實(shí)現(xiàn)的優(yōu)缺點(diǎn)
| 克隆 | 元表 | |
| 優(yōu)點(diǎn) | 創(chuàng)建出新table,可遍歷 | 創(chuàng)建迅速,占用內(nèi)存少 |
| 缺點(diǎn) | 當(dāng)被克隆的table較大的時(shí)候,耗時(shí)較久,并且占用內(nèi)存較多 | 不可以設(shè)置原table已有的值為nil,不可使用pairs和ipairs遍歷 |
預(yù)告
有沒有一種方式創(chuàng)建出來的新table,可以兼顧克隆和元表兩者的優(yōu)點(diǎn),既創(chuàng)建速度快,占用內(nèi)存少,又可以肆意修改,并且完全不影響到原來的table還能支持遍歷呢?
下篇見。