- N +

js有for了為什么還要有foreach?foreach的用法

node.js中的forEach是同步還是異步

node里幾乎所有用到回調函數的地方,都是異步的,回調函數后面的代碼很可能比回調函數中的代碼后先執行,特別是數據庫操作。當然,node也提供了同步版本的函數,例如文件操作,fs.readFileSync()是fs.readFile()的同步版本。那么問題來了,forEach()是不是異步的呢?按理說,沒有加Sync,應該是異步的呀。復制代碼代碼如下:vararr=['a','b','c']

;varstr='123'

;arr.forEach(function(item){str+=item;while(true){};//用一個死循環,卡死它~~})

;console.log(str);運行上面的代碼,結果它就這么卡死了,沒有任何輸出。。

所以說,node里的forEach()是同步的!!

第一次用node的時候,沒有考慮過這個問題,按同步的寫了,寫突然想到,測試后虛驚一場,以為以前的代碼都寫錯了。

forEach和map有什么區別

map與forEach其實都是JS中,對array進行遍歷的方法,區別在于map是存在返回值的,而forEach返回值為undefined

我對map的理解是,這個方法對一個數組arr1中的每一個元素進行遍歷(傳遞給一個數組,參數為(item,index,arr1)),返回值保存到另一個數組中,遍歷結束后,整個方法返回這個數組

require和request有什么區別

1require和request的意義不同2require是指在Node.js中引入另一個模塊,類似于Java中的import或include。而request是指向另一個服務器發出請求并接收響應的操作,常用于獲取HTTP接口數據。3require和request都是在開發中常用的操作,需要靈活掌握和運用。

什么是跨域,跨域的實現方式有哪些

查了一些資料,再結合我之前的了解,給大家介紹一下,如果有說的不對的地方,請大家留言指正。

什么是跨域

瀏覽器有一個毛病(策略):請求url的協議、域名、端口必須相同,才允許訪問(通信),否則就不允許訪問,是跨域。

https(協議)://www.wukong.com(域名和端口)/index.html

比如:

https://www.wukong.com/index.html

http://www.wukong.com/index.html

這樣就不允許通信,因為協議不同。

完整的舉個例子:

你有服務器A和服務器B,服務器A上存著CSS和JS腳本,服務器B上存著HTML,HTML頁面上的CSS和JS都是鏈接的服務器A上面的。

然后用瀏覽器打開服務器B上面的xxx.html,頁面打開后可以正常渲染出樣式,可以運行JS腳本,這樣就是跨域名,跨端口,跨協議。

如何解決跨域

JSONP:利用了script標簽不受同源策略的限制,通過script加載服務器A的資源。

Proxy代理:使用服務器接口做代理,因為同源策略之針對瀏覽器。

CORS:跨域資源共享,這個就是瀏覽器后悔了,出了一個跨域訪問機制(XMLHttpRequest),低版本IE不支持。

Postmessage:HTML5新增的跨域機制。

Nginx反向代理:相當于Proxy代理。

希望我的回答可以幫助到你!

為什么Java不支持運算符重載

Java不支持運算符重載=小白也能學編程

Java之所以不支持運算符重載,并不是如下原因:

會使JVM變得復雜、性能下降:君不見C++內置運算符重載的能力?C++的性能在任何時代秒殺Java相信沒有爭議。便于靜態分析、工具化等:一葉障目、不見泰山。運算符重載只是一種動態特性,動態語言的形式化靜態分析方法已經有成熟的方法論。Java是面向對象語言:Ruby是比Java更徹底的面向對象的語言,然而它對運算符重載的支持非常優秀,在Ruby中一切都是對象,幾乎一切都可以override。

不支持運算符重載的根本原因,是源自JamesGosling設計Java的初衷:那就是要讓Java的學習門檻足夠低,這樣才能讓這個編程語言被更多的人使用,從而擁有最大的市場占有率。

Java誕生之前,基本上是C/C++的天下。光C語言的一個指針,就嚇退了多少莘莘學子?C++引入更多的動態特性:多態、多重繼承、函數重載、函數重寫、運算符重載、泛型……這更不知道讓多少人望而卻步!

正是在那樣的大環境下,JamesGosling才萌生了“開發一個小白都能上手”的編程語言的念頭。

運算符重載的底層思想并不是面向對象

運算符重載的底層邏輯來自函數式編程。它的祖師爺是Lisp,一個“從來被模仿、從未被超越”的神級語言。

可以負責任地講,如今流行的Python、Javascript、Typescript、Go、Ruby、Haskell、Scala、Groovy等,在動態高級特性上都是在不斷模仿60多年前的Lisp。包括Java從誕生起就在鼓吹的垃圾回收等優點,全部都是“偷師”Lisp。有興趣的小伙伴可以自行下載Lisp的發明者——JohnMcCarthy老爺爺1960年發表的GC論文。

函數式語言的核心思想其實是數學。

說得更白話一點:通過數學表達式描述問題,而不是人肉模擬解答過程。問題描述完了,也就解決了——運行時處理執行細節。

說得更學院派一點:通過無狀態的函數加以其他優化特性,將這些函數組件進行拼接。

看到這里,估計有不少人要來拍磚:運算符重載看起來那么復雜,明明可以定義方法或者函數來解決,除了裝逼格,沒有實用價值。

筆者這里回應一下:數學本來就不是普通大眾擅長的,數學的目的就是用最簡潔的方式來解決最復雜的問題。所以函數式語言從誕生之初,就沒有想過要蕓蕓眾生。它追求的是大道至簡。

這里來看一個例子:計算一組數據(假設放在一個一維數組中)的標準差。

如果不采用函數式編程,采用通常的面向過程或者面向對象的編程范式,那么只能:

第一步,先通過循環體(for/foreach/while等),挨個遍歷求出平均值mean;

第二步,再來一次循環,挨個求與mean的差值并平方,然后逐個累加得到平方合sumOfSquares;

第三步,對sumOfSquares調用平方根函數,求出最終值standardDeviation。

下面我們來進化一點:

有基本函數式編程概念的小伙伴可能會寫出如下的簡化范式(這里以Ruby為例):

mean=a.inject{|x,y|x+y}/a.size

sumOfSquares=a.map{|x|(x-mean)**2}.inject{|x,y|x+y}

standardDeviation=Math.sqrt(sumOfSquares/(a.size-1))

但是真正的函數式編程高手是會這樣寫的:

第一步:寫一個通用的數學意義上的復合函數(f(g(x))=f*g(x))的表達:

moduleFunctional

defapply(enum)

enum.map&self

end

alias|apply

defreduce(enum)

enum.inject&self

end

alias<=reduce

defcompose(f)

ifself.respond_to?(:arity)&&self.arity==1

lambda{|*args|self[f[*args]]}

else

lambda{|*args|self[*f[*args]]}

end

end

alias*compose

end

第二步:把計算標準差所需要的各個元素的數學表達列示好:

sum=lambda{|x,y|x+y}#Afunctiontoaddtwonumbers

mean=(sum<=a)/a.size#Orsum.reduce(a)ora.inject(&sum)

deviation=lambda{|x|x-mean}#Functiontocomputedifferencefrommean

square=lambda{|x|x*x}#Functiontosquareanumber

第三步:像寫標準差的數學表達式一樣,一步到位:

standardDeviation=Math.sqrt((sum<=square*deviation|a)/(a.size-1))

總結

Java之所以流行,并不是因為其語言設計得最優秀,相反地,在很多地方——比如泛型、Lambda、完全面向對象等設計上都存在不足。它的成功在于:揚長避短,把所有牛X的高級語言特性在一開始全部都拋棄,留一個最小核,然后通過營銷,大規模地培養本語言陣營的程序員,建立各種各樣的“輪子”,成就了巨無霸的生態;在站穩格局之后,慢慢地再逐步添加回來一些以前拋棄的其他語言的優秀特性——這是一種比較實用的策略,但是帶來的惡果就是:歷史包袱比較重,導致新特性很多時候是“半殘”的。

回到運算符重載本身,對于高手,可以利用該特性寫出極具“魔性”、接近數學語言的代碼,這樣的代碼可以體現“極簡之美”——但是,一個不利影響就是:數學不好的小伙伴,不容易看得懂,也很難體會其中蘊含的“數學之美”。

返回列表
上一篇:
下一篇: