悟透一個(gè)小竅門,你就能舉一反三掌握所有編程語(yǔ)言
當(dāng)你程序員當(dāng)久了,你會(huì)慢慢了解到,許多真 . 大佬都是編程語(yǔ)言通。他們?cè)趶氐渍莆樟艘婚T語(yǔ)言之后,就能夠很自信的覺得自己能夠輕松掌握別的語(yǔ)言。這種能力可把許多人饞哭了,到底是怎么回事?為什么別人能夠輕松駕馭所有語(yǔ)言,而我不行?
有的人甚至?xí)岩纱罄袀冊(cè)诖蹬?,怎么可能?huì)有這樣厲害的人。
事實(shí)上,這種能力是真實(shí)存在的,因?yàn)槲?,一個(gè)小小的前端開發(fā),就已經(jīng)具備這個(gè)能力了。今天我跟大家分享一個(gè)小訣竅,讓你也能逐步擁有這個(gè)能力。
首先我們要明確一個(gè)前提,大多數(shù)編程語(yǔ)言都是非常相似的,因此我們才能夠做到快速掌握別的語(yǔ)言,只是你可能還沒有感受到而已。
所以這個(gè)竅門說穿了其實(shí)就非常簡(jiǎn)單,要成為編程語(yǔ)言通,我們只需要找到他們的相似性,就可以了。
我們可以把常用的編程語(yǔ)言分為兩個(gè)大類。
先以我們最熟悉的 JavaScript 為代表,來(lái)觀察一下類似語(yǔ)言的語(yǔ)法。
首先是 JavaScript。
let a = 10
function foo() {}
for (let i = 0; i <= 10; i++) {}
然后是你可能沒學(xué)過的 go 語(yǔ)言。
var a string = 'hello world'
var b c int = 1, 2
func main() {}
這個(gè)時(shí)候,如果你對(duì) JS/TS 比較熟悉的話,你會(huì)發(fā)現(xiàn)神奇的事情,你居然看懂了沒有學(xué)過的語(yǔ)言。
我們?cè)賮?lái)看一下 dart 語(yǔ)言,哎呀,糟糕,又看懂了。
var x = 1;
var hex = 0xDEADBEEF;
var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
message.write('!');
}
再來(lái)看看 Swift,哦豁,還能看得懂?
/* 我的第一個(gè) Swift 程序 */
var myString = "Hello, World!"
print(myString)
let decimalInteger = 17 // 17 - 十進(jìn)制表示
let binaryInteger = 0b10001 // 17 - 二進(jìn)制表示
let octalInteger = 0o21 // 17 - 八進(jìn)制表示
let hexadecimalInteger = 0x11 // 17 - 十六進(jìn)制表示
func runoob(site: String) -> String {
return (site)
}
import Cocoa
var someInts:[Int] = [10, 20, 30]
for var index = 0; index < 3; ++index {
print( "索引 [\(index)] 對(duì)應(yīng)的值為 \(someInts[index])")
}
這里有一個(gè)很有意思的事情就是,你輕松的發(fā)現(xiàn)了這些語(yǔ)言居然跟你學(xué)過的 JavaScript 擁有如此相似之處。
所以 JavaScript 雖然在某種程度上被吐槽得非常多,各種缺點(diǎn),但是很顯然,后來(lái)的許多語(yǔ)言的語(yǔ)法設(shè)計(jì)都參考了 JavaScript,學(xué)會(huì)了 JavaScript,實(shí)際上就代表你已經(jīng)具備輕松掌握別的語(yǔ)言的能力。
但是很多前端依然沒有這個(gè)自信,為什么呢?
因?yàn)?JavaScript 是一個(gè)弱類型語(yǔ)言,它缺乏類型系統(tǒng)。
因此,我們只需要進(jìn)一步掌握 TS,就能成為某一類語(yǔ)言的語(yǔ)言通!
這里我們要明確一個(gè)非常關(guān)鍵的信息,那就是以 TS 為代表的這一類語(yǔ)言,有一個(gè)非常明確的特征:類型后置。
這類語(yǔ)言的語(yǔ)法設(shè)計(jì)通常會(huì)在聲明的前面給一個(gè)關(guān)鍵詞來(lái)表示當(dāng)前我正在聲明一個(gè)變量,然后在變量后面明確該變量的類型。
var a: string = 10
包括最近比較火熱的 rust 也是一門典型的類型后置的語(yǔ)言,不要騙我,你一定能讀懂下面這行代碼。
fn main() {
let x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}
而另外一類以 C 語(yǔ)言為代表的語(yǔ)言,它也有一個(gè)非常明確的特征:類型前置。
int x = 10; // 整型變量 x 初始化為 10
float pi = 3.14; // 浮點(diǎn)型變量 pi 初始化為 3.14
char ch = 'A'; // 字符型變量 ch 初始化為字符 'A'
extern int d = 3, f = 5; // d 和 f 的聲明與初始化
int d = 3, f = 5; // 定義并初始化 d 和 f
byte z = 22; // 定義并初始化 z
int max(int num1, int num2) {
/* 局部變量聲明 */
int result;
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
如果你沒有學(xué)過 C 語(yǔ)言的話,你會(huì)覺得 C 語(yǔ)言的代碼讀起來(lái)理解難度會(huì)高一點(diǎn)。這是正常的。因?yàn)轭愋颓爸玫睦斫獬杀緯?huì)高很多。我們需要閱讀到后面才能知道這一行代碼在干什么。
因此新出的語(yǔ)言都是采用類型后置的設(shè)計(jì)方式,JavaScript 能夠流行起來(lái),很大一部分原因是因?yàn)樵?C 系語(yǔ)言稱霸的時(shí)候,找到了學(xué)習(xí)成本更低的語(yǔ)法設(shè)計(jì)。
著名的 Java 也是一門典型的類型前置的語(yǔ)言。類型前置理解困難還在于面向?qū)ο笾?,?jīng)常會(huì)出現(xiàn)自定義的類型,例如在 Java 代碼中這種類型的句式非常常見。
Puppy myPuppy = new Puppy( "tommy" );
對(duì)比一在 js 中的理解難度。
var myPuppy = new Puppy( "tommy" )
我們會(huì)發(fā)現(xiàn),同樣的代碼用 js 理解起來(lái)要簡(jiǎn)單得多。
語(yǔ)言通的大佬們,敏銳的發(fā)現(xiàn)了這個(gè)區(qū)別:類型前置與類型后置。除此之外,所有的語(yǔ)言都具備高度的相似性。
當(dāng)你沒有發(fā)現(xiàn)這個(gè)區(qū)別,只會(huì) JS 的你,去學(xué)習(xí) C++ 你會(huì)特別痛苦,因?yàn)槟愀杏X差異太大了。但是當(dāng)你悟透了類型前置與后置的區(qū)別之后,學(xué)習(xí)難度就會(huì)神奇的降低特別多。來(lái)感受一下這段代碼,看能搞得懂不。
#include <iostream>
using namespace std;
class Box
{
public:
double length; // 長(zhǎng)度
double breadth; // 寬度
double height; // 高度
// 成員函數(shù)聲明
double get(void);
void set( double len, double bre, double hei );
};
// 成員函數(shù)定義
double Box::get(void)
{
return length * breadth * height;
}
void Box::set( double len, double bre, double hei)
{
length = len;
breadth = bre;
height = hei;
}
int main( )
{
Box Box1; // 聲明 Box1,類型為 Box
Box Box2; // 聲明 Box2,類型為 Box
Box Box3; // 聲明 Box3,類型為 Box
double volume = 0.0; // 用于存儲(chǔ)體積
// box 1 詳述
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// box 2 詳述
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// box 1 的體積
volume = Box1.height * Box1.length * Box1.breadth;
cout << "Box1 的體積:" << volume <<endl;
// box 2 的體積
volume = Box2.height * Box2.length * Box2.breadth;
cout << "Box2 的體積:" << volume <<endl;
// box 3 詳述
Box3.set(16.0, 8.0, 12.0);
volume = Box3.get();
cout << "Box3 的體積:" << volume <<endl;
return 0;
}
有沒有感覺其實(shí)你是看得懂的?是不是變簡(jiǎn)單了?
一、類型與類型推導(dǎo)
在不同的語(yǔ)言中,對(duì)類型的設(shè)計(jì)有細(xì)微的差異,例如數(shù)字有的語(yǔ)言是 int ,有的語(yǔ)言是 number,有的語(yǔ)言還有 bigInt,字符串有的語(yǔ)言直接就是 string,有的語(yǔ)言里還有 char。因此我們學(xué)習(xí)的時(shí)候要花一點(diǎn)點(diǎn)時(shí)間去區(qū)分不同的類型細(xì)節(jié),在 rust 語(yǔ)言中,因?yàn)閷?duì)內(nèi)存分配敏感,因此光是整型,都有好幾種類型。
let x: u8 = 2
let y: u16 = 15
你還需要了解有符號(hào)整型,無(wú)符號(hào)整型,浮點(diǎn)型等細(xì)節(jié),學(xué)習(xí)成本非常低。
除此之外呢,許多前端沒把類型編程掌握好。例如在 TS 中,我們引入了類型機(jī)制,并且開始有泛型。很多人就懵掉了。不過沒關(guān)系,我們只需要幾分鐘就能掌握它。
在現(xiàn)代語(yǔ)言中,由于類型自動(dòng)推導(dǎo)開始越來(lái)越成熟,因此許多語(yǔ)言會(huì)在聲明的時(shí)候巧妙利用類型推導(dǎo)機(jī)制省略具體類型的聲明,所以你單看下面的代碼,你都不敢說我到底寫的是哪門語(yǔ)言。
var a = 10
因此我們?cè)趯W(xué)習(xí) TS 的時(shí)候,一定要把類型推導(dǎo)徹底掌握透徹,他是你成為語(yǔ)言通的關(guān)鍵。
二、兩種不同的開發(fā)范式
目前有兩種主流的開發(fā)范式,函數(shù)式編程與面向?qū)ο缶幊獭S捎诟髯缘奶厥庠?,就?dǎo)致了許多前端可能會(huì)對(duì)面向?qū)ο缶幊谭浅5哪吧瑢?duì)函數(shù)式編程會(huì)稍微親近一些
但是作為一個(gè)語(yǔ)言通,不懂面向?qū)ο缶幊炭隙ㄊ菄?yán)重偏科的,這會(huì)極大的影響你的進(jìn)步,比如許多前端可能就不懂重載,多態(tài)等基礎(chǔ)概念。
不過這個(gè)時(shí)候,我們也能發(fā)現(xiàn)前端有一個(gè)天然的優(yōu)勢(shì),那就是后端其實(shí)需要函數(shù)式編程的場(chǎng)景到目前為止來(lái)看并不多,許多后端開發(fā)并沒有機(jī)會(huì)接觸函數(shù)式編程,因此大多數(shù)后端也是偏科的
三、TS 的先進(jìn)性
在類型編程中,縱觀整個(gè)編程語(yǔ)言界,TS 的類型推導(dǎo)都算的上是最強(qiáng)大和最先進(jìn)的。我們搞前端的要有這種技術(shù)自信,這非常關(guān)鍵。
之所以會(huì)出現(xiàn)這種局面是因?yàn)榍岸嗣媾R的類型問題更為復(fù)雜。當(dāng)然現(xiàn)在由于發(fā)展得太過頭了,類型體操反而成為了許多人厭棄 TS 的原因。我們只需要在使用的時(shí)候自己稍微克制一下,就能很好的發(fā)揮 TS 的長(zhǎng)處。他的優(yōu)秀毋容置疑。
四、總結(jié)
我們可以將編程語(yǔ)言分為類型前置與類型后置,除此之外,編程語(yǔ)言其實(shí)就長(zhǎng)得差不多了。
在類型后置語(yǔ)言中,JavaScript 是一門經(jīng)得起時(shí)間考驗(yàn)的設(shè)計(jì)語(yǔ)言,他先進(jìn)的語(yǔ)法設(shè)計(jì)引領(lǐng)了整個(gè)編程語(yǔ)言界,因此,深入掌握 JS + TS ,結(jié)合本文的小竅門,我們搞前端的就能夠輕松成為編程界的語(yǔ)言通。