今天看到一段代碼
發現在調用函式的使用手段 用了一個我沒想過的手法
先請看下面這邊
function selfPush(){
jQuery.ajax({
type: "POST",
data: {
rtecontent: "[div]"+content+"[/div]",
pwd: getVal("pwd"),
type: getVal("type"),
code: getVal("code"),
subbsn: getVal("subbsn"),
title: getVal("title"),
sign: getVal("sign"),
ptype: getVal("ptype"),
bbsign: getVal("bbsign"),
ccsign: getVal("ccsign"),
},
function getVal(input) {
return document.getElementsByName(input)[0].value;
}
這邊的重點是我自己來寫這段,並不會有這樣子風格的寫法產生!
看到這招,覺得格外有趣◑ω◐。
依照以前學過來的經驗 我應該會把這些data設定為變數
這邊我就寫原生的JS就好 當然用JQuery是差不多意思
如下
pwd=document.getElementsByName(pwd)[0].value;
type=document.getElementsByName(type)[0].value;
code=document.getElementsByName(code)[0].value;
subbsn=document.getElementsByName(subbsn)[0].value;
title=document.getElementsByName(title)[0].value;
sign=document.getElementsByName(sign)[0].value;
ptype=document.getElementsByName(ptype)[0].value;
bbsign=document.getElementsByName(bbsign)[0].value;
ccsign=document.getElementsByName(ccsign)[0].value;
ajax的裡面部分
其實光是寫到上面變數 各位看下來應該都懂 但我還是貼出來示意XD
就像是如下
pwd: pwd;
type: type;
code: code;
subbsn: subbsn;
title: title;
sign: sign;
ptype: ptype;
bbsign: bbsign;
ccsign: ccsign;
發現到這招覺得「程式碼優化」這個議題可以好好研究!!
因為這樣對比下來,我發現getVal的這種手段頗聰明的。
那我好奇的是這樣子是否比較簡潔,又另一個議題是在效能上是否會有差別?
各位會用什麼名詞或觀念解釋這樣子的coding技巧?
在寫程式的時候也有相似的其他招數嗎?
歡迎各位前輩來討論這樣子寫的風格,以及效能,進行深入探討與分析。
嘛~~~
這個其實還真不知道該如何說。
雖然你說 getVal 很好。但其實我倒是覺得還好。
不能說它不好。只是還不到位。
不過我想你還未學好VUE、React、Angular這一類的前端框架。
你會發現你說的getVal。根本是個屁。
所以我大概可以理解 froce 可能想說的話。
不過我也會借用他的話。
其實你高興就好。
但你要知道一件事。你目前觸碰到的東西。都還只在邊邊。
在你認為這樣寫法很好不錯的感覺。
你就會停止進步了。
其實有更方便更好的寫法存在。
DRY以外還要注意一件事,就是你有沒有想過,[0]這操作是不是永遠取的到?
符合DRY的話,定這個getVal的函數,他用途就只是取value,萬一你還要對這個元素做操作呢?
下面這種操作可是很常見的
jQuery.ajax({
type: "POST",
data: {
rtecontent: "[div]"+content+"[/div]",
pwd: getVal("pwd"),
type: getVal("type"),
code: getVal("code"),
subbsn: getVal("subbsn"),
title: getVal("title"),
sign: getVal("sign"),
ptype: getVal("ptype"),
bbsign: getVal("bbsign"),
ccsign: getVal("ccsign"),
},
success: function(){
....
// 譬如清空密碼槽、disable、隱藏密碼槽
}
})
這樣的話你用getVal有什麼特殊意義嗎?
還不如用個
const pwd = $('#pwd')
// 你後面要用就能 pwd.val()就好,元素也能復用
jQuery.ajax({
type: "POST",
data: {
pwd: pwd.val(),
},
}).done(function(){
pwd.hide()
})
反正光一眼瞄過去能吐槽的就三大點了...
@froce 感謝解答!
關於第一點我的確有好奇,這樣寫是否都能抓到,謝謝提出。
關於第二點我真的沒想到有這樣子的可能,的確是超級漏洞,是個問題。
關於第三點的話,框架我真的是還沒摸到邊邊,完全有道理。
大師果然有經驗跟見解,是我大驚小怪了。
以為這是個聰明的小巧招,實則只是普普通通的一般寫法。
我把JS看的太淺了。
非常感謝,學習到很多,心態上也是(。◕∀◕。)。
這次選您為最佳解答,也感謝froce精闢的戳中要害!
非常有幫助。
我在使用React之前是這樣做的,我寫了一個Collector,給他Form之後會幫我蒐集成我要的資料格式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<title>Document</title>
</head>
<body>
<form id="demoform">
<div>
<p>normal input</p>
<label>帳號<input name="account"></label>
<br>
<label>密碼<input name="password"></label>
<br>
<label>行星<input name="planet"></label>
</div>
<div>
<p>radio button</p>
<label><input type="radio" name="goal" value="lv-426">LV-426</label>
<label><input type="radio" name="goal" value="lv-427">LV-427</label>
<label><input type="radio" name="goal" value="lv-428">LV-428</label>
<label><input type="radio" name="goal" value="lv-429">LV-429</label>
</div>
<div>
<p>check box</p>
<label><input type="checkbox" name ="tool" value="gun">gun</label>
<label><input type="checkbox" name ="tool" value="sword">sword</label>
<label><input type="checkbox" name ="tool" value="aox">aox</label>
<label><input type="checkbox" name ="tool" value="money">money</label>
</div>
<div>
<p>selector</p>
<select name="pet">
<option value="">請選擇你最愛的寵物</option>
<option value="Facehugger">Facehugger</option>
<option value="Dog">Dog</option>
<option value="Cat">Cat</option>
<option value="Hamster">Hamster</option>
<option value="Parrot">Parrot</option>
<option value="Spider">Spider</option>
<option value="Goldfish">Goldfish</option>
</select>
</div>
<div>
<p>text area</p>
<label><textarea name="remark" style="width:300px;height:150px;" ></textarea></label>
</div>
</form>
<script>
function collectData(formID){
var formdata = $(formID).serializeArray()
var columns = Array.from(new Set(formdata.map(item => {return item.name})))
var new_data = columns.map( item => {
let temp_ary = formdata.filter( st => {return st.name === item})
let temp_obj = new Object()
temp_obj[item] = temp_ary.length > 1 ? temp_ary.map(ck => {return ck.value}) : temp_ary[0].value
return temp_obj
})
console.log(new_data)
}
</script>
<button onclick="collectData('#demoform')">click me to collect data</button>
</body>
</html>
在寫程式的時候也有相似的其他招數嗎?
我喜歡使用 Lazy Loading 的方式宣告不常使用到的變數.
// class 中宣告的屬性
private $_variables = array();
下方使用
// 這是個PHP示範
/**
* This is a private method used to handle variables.
*
* @param string $variable The variable name.
* @return mixed Returns the variable value.
*/
private function _variable(string $variable): mixed
{
if (isSet($this->$variable)) {
return $this->$variable;
}
$fn = sprintf("%s_%s", '_get_variable', $variable);
$this->$variable = $this->$fn();
return $this->$variable;
}
/**
* This magic method is used to get the value of a property that was not declared explicitly.
*
* @param string $name The property name.
* @return mixed|null Returns the value of the property if it exists or null otherwise.
*/
public function __get(string $name): mixed
{
return $this->_variables[$name] ?? null;
}
/**
* This magic method is used to set the value of a property that was not declared explicitly.
*
* @param string $name The property name.
* @param mixed $value The value to set for the property.
* @return void
*/
public function __set(string $name, mixed $value): void
{
$this->_variables[$name] = $value;
}
這時候只要宣告一個 function
private function _get_variable_test(): string
{
return "this is test";
}
我就可以使用 $this->_variable('test') 來得到我所需要的 return.
風格或是效能?
剛開始寫程式的時候都會希望能有什麼新潮或很騷的方式去寫code.
其實後面, 不管是什麼方式, 減少 code review 跟 Debug 時間才是最重要的.
...除非你是寫底層語言.
題外話
現在框架大部分都用 axios 了吧@@
可以將表單數據打包成一個對象,而不是分別傳遞每個參數。這樣可以使代碼更簡潔,易於維護和擴展
function selfPush() {
const formData = {
rtecontent: `[div]${getVal('content')}[/div]`,
pwd: getVal('pwd'),
type: getVal('type'),
code: getVal('code'),
subbsn: getVal('subbsn'),
title: getVal('title'),
sign: getVal('sign'),
ptype: getVal('ptype'),
bbsign: getVal('bbsign'),
ccsign: getVal('ccsign'),
};
jQuery.ajax({
type: 'POST',
data: formData,
// ...
});
}
你貼的程式碼看起來是一段把 form 表單內的 input 收集起來透過 jQuery Ajax 送出的程式碼,建議可以把 HTML 部分的內容也補齊,這樣你的問題會完整一些,其他人就不用透過通靈的方式去猜測 HTML 的內容。
利用 getVal()
去簡化程式碼是一個蠻常見的程式技巧,但如果你再拉高一個層級去看的話,這應該是對某個 <form>
底下所有的 input 內容打包成 data 的操作。其實這在瀏覽器的 Web API FormData() 就已經有提供這個功能了,所以你不太需要自己再手刻一個包裝功能。
FormData()
的使用範例 (引用前面提到的連結) 如下:
<form id="form">
<input type="text" name="text1" value="foo" />
<input type="text" name="text2" value="bar" />
<input type="text" name="text2" value="baz" />
<input type="checkbox" name="check" checked disabled />
<button name="intent" value="save">Save</button>
<button name="intent" value="saveAsCopy">Save As Copy</button>
</form>
<output id="output"></output>
const form = document.getElementById("form");
const submitter = document.querySelector("button[value=save]");
const formData = new FormData(form, submitter);
const output = document.getElementById("output");
for (const [key, value] of formData) {
output.textContent += `${key}: ${value}\n`;
}
另外要提的一件事情是那個 content
和 pwd, type, code, subbsn, title, sign, ptype, bbsign, ccsign 這些變數都不是透過 selfPush() 的參數傳入的,這其實不是很好的程式風格。其實 jQuery 或是 document.getElementsByXXX 的程式碼都有類似的問題,所以後面才會透過元件化的方式去管理越來越複雜的網頁結構,基本上 vue, react 這些前端框架都有元件化的思維了。
大概是這樣,以上