整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          如何成為一名前端開發之HTML入門

          如何成為一名前端開發之HTML入門

          末有福利

          前端開發,入門簡單,有一臺可以運行多款瀏覽器的電腦,能聯網查詢資料即可。深入的部分,需要更多的理論知識、肯鉆研的精神。 前端開發,需要入門了解的屈指可數,主要就是如下幾個大方面:

          背景知識

          軟件安裝

          文本編輯器

          • vscode(推薦使用,功能強大)
          • Sublime Text
          • NodePad++

          瀏覽器

          Firefox,Chrome , Opera, Safari, Internet Explorer and Microsoft Edge

          版本控制

          Git GitHub

          構建工具

          • Webpack
          • Gulp

          Web standards

          Web standards ,主要定義瀏覽器端,功能接口標準的,標準的具體實現,由不同的瀏覽器廠商完成。

          當下使用的web技術

          主流瀏覽器

          Firefox, Chrome , Opera, Safari, Internet Explorer and Microsoft Edge

          協議

          協議,主要用于通信。前后端不是獨立的,彼此通過協議,互換信息,web系統才能運行正常

          • http
          • https
          • socket

          HTML, CSS, and JavaScript

          開發工具

          • 各瀏覽的DevTool,便于調試
          • Linters插件
          • Minify工具
          • CDN等
          • 測試工具
          • js庫和前端框架(站點構建的更快、更高效)

          服務端語言

          Python, NodeJS, Deno, Go, Rust 
          

          面臨的挑戰

          瀏覽器兼容

          Web standards,各實現廠商不同,支持力度不同,瀏覽器兼容問題自然存在

          響應式設計

          廠商的不同,展示場景的不同,意味著不能全篇一律敲定,需要動態變化展示內容

          性能

          天下站點,只有快,才能留住用戶

          易用性

          站點的訪問人群不同,要具備普適性, 都能輕松使用。

          國際化

          國際語言眾多,需要盡可能的多支持

          安全性

          用戶隱私數據保護

          HTML

          html基礎概念

          html元素

          當然,也有例外,不是這種格式的

          # Empty elements, or (void elements.) 
          <img src="https://raw.githubusercontent.com/mdn/beginner-html-site/gh-pages/images/firefox-icon.png">
          復制代碼

          html元素嵌套

          <p>My cat is <strong>very</strong> grumpy.</p>
          復制代碼

          塊元素和行內元素

          塊元素,獨占一行;行內元素,按先后順序,排列 這些與css的display不同,不影響元素能包含哪些元素,能被哪些元素包含

          元素屬性

          其中,也存在一種特殊的屬性:Boolean attributes

          <input type="text" disabled>
          # 等效于
          <input type="text" disabled="disabled">
          復制代碼

          另外,也會存在一些特殊的寫法。推薦都是key="value"形式

          <a href=https://www.mozilla.org/>favorite website</a>
          復制代碼

          html文檔結構

          不管多少連續的空白,瀏覽器都會解析會一個空格

          <!DOCTYPE html> # 定義解析格式
          <html> # 文檔的root 
            <head> #定義源數據地方 
              <meta charset="utf-8">
              <title>My test page</title>
            </head>
            <body> # 文檔的可見內容部分
              <p>This is my page</p>
            </body>
          </html>
          復制代碼

          元數據等請移步參考

          html特殊字符

          <, >,",' and &, 這是html自身使用的,如果用戶需要展示,那么需要轉義



          html注釋

          <!-- 
           <p>I am!</p> 
          -->
          復制代碼

          html 多媒體

          image

          • 普通的圖片

          alt描述圖片

          # 推薦添加alt,而不是text子元素節點添加
          <img src="images/dinosaur.jpg"
              alt="The head and torso of a dinosaur skeleton;
                   it has a large head with long sharp teeth">
          復制代碼

          caption添加標題

          <figure>
            <img src="images/dinosaur.jpg"
                 alt="The head and torso of a dinosaur skeleton;
                      it has a large head with long sharp teeth"
                 width="400"
                 height="341">
           <figcaption>A T-Rex on display in the Manchester University Museum.</figcaption>
          </figure>
          復制代碼
          • 響應式圖片

          根據展示設備尺寸的不同,加載不同的圖片

          <img srcset="elva-fairy-480w.jpg 480w,
                      elva-fairy-800w.jpg 800w"
              sizes="(max-width: 600px) 480px,
                     800px"
              src="elva-fairy-800w.jpg"
              alt="Elva dressed as a fairy">
          復制代碼

          設備尺寸相同,但是分辨率不同

          <img srcset="elva-fairy-320w.jpg,
                      elva-fairy-480w.jpg 1.5x,
                      elva-fairy-640w.jpg 2x"
              src="elva-fairy-640w.jpg"
              alt="Elva dressed as a fairy">
          復制代碼

          利用picture,不同設選擇加載不同的圖片

          <picture>
            <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
            <source media="(min-width: 800px)" srcset="elva-800w.jpg">
            <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
          </picture>
          復制代碼

          picture+svg

          <picture>
            <source type="image/svg+xml" srcset="pyramid.svg">
            <source type="image/webp" srcset="pyramid.webp"> 
            <img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
          </picture>
          復制代碼

          audio

          單一url 瀏覽器廠商,針對音頻的支持格式不是不同的,譬如: MP3, MP4 and WebM

          <video src="rabbit320.webm" controls>
            <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.webm">link to the video</a> instead.</p> 
          </video>
          復制代碼

          瀏覽器適配問題

          <audio controls>
            <source src="viper.mp3" type="audio/mp3">
            <source src="viper.ogg" type="audio/ogg">
            <p>Your browser doesn't support HTML5 audio. Here is a <a href="viper.mp3">link to the audio</a> instead.</p>
          </audio>
          復制代碼

          video

          單一url 瀏覽器廠商,針對視頻的支持格式不是不同的

          <video src="rabbit320.webm" controls>
            <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.webm">link to the video</a> instead.</p> 
          </video>
          復制代碼

          瀏覽器適配問題

          <video controls width="400" height="400"
                 autoplay loop muted preload="auto" 
                 poster="poster.png">
            <source src="rabbit320.mp4" type="video/mp4">
            <source src="rabbit320.webm" type="video/webm">
            <p>Your browser doesn't support HTML video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p>
          </video>
          復制代碼

          svg

          image引用svg

          <img 
              src="equilateral.svg" 
              alt="triangle with all three sides equal"
              height="87"
              width="100" />
          復制代碼

          html引用svg

          <svg width="300" height="200">
              <rect width="100%" height="100%" fill="green" />
          </svg>
          復制代碼

          iframe等中引用svg

          <iframe src="triangle.svg" width="500" height="500" sandbox>
              <img src="triangle.png" alt="Triangle with three unequal sides" />
          </iframe>
          復制代碼

          canvas

          canvas與svg不同,canvas基于像素,svg基于矢量圖

          #html
          <canvas id="my-canvas" width="600" height="400"></canvas>
          復制代碼

          嵌入元素

          iframe, embed and object
          

          iframe

          <iframe src="https://developer.mozilla.org/en-US/docs/Glossary"
                  width="100%" height="500" frameborder="0"
                  allowfullscreen sandbox>
            <p> 
              <a href="https://developer.mozilla.org/en-US/docs/Glossary">
                 Fallback link for browsers that don't support iframes
              </a>
            </p>
          </iframe>
          復制代碼

          html table

          樣式指定

          <table>
            <tr>
              <th>Data 1</th>
              <th style="background-color: yellow">Data 2</th>
            </tr>
            <tr>
              <td>Calcutta</td>
              <td style="background-color: yellow">Orange</td>
            </tr>
            <tr>
              <td>Robots</td>
              <td style="background-color: yellow">Jazz</td>
            </tr>
          </table>
          復制代碼

          更好的樣式指定

          col 一次指定即可

          <table>
            <colgroup>
              <col> # 定義在colgroup中,與th個數對應
              <col style="background-color: yellow">
            </colgroup>
            <tr>
              <th>Data 1</th>
              <th>Data 2</th>
            </tr>
            <tr>
              <td>Calcutta</td>
              <td>Orange</td>
            </tr>
            <tr>
              <td>Robots</td>
              <td>Jazz</td>
            </tr>
          </table>
          復制代碼

          全部設置

          <colgroup>
            <col style="background-color: yellow" span="2">
          </colgroup>
          復制代碼

          如果你現在也想學習前端開發技術,在學習前端的過程當中有遇見任何關于學習方法,學習路線,學習效率等方面的問題,你都可以申請加入我的Q群:前114中6649后671,里面有許多前端學習資料 大廠面試真題免費獲取,希望能夠對你們有所幫助。

          擊上方 "程序員小樂"關注, 星標或置頂一起成長

          每天凌晨00點00分, 第一時間與你相約


          每日英文

          Someday, you will find the one, who will watch every sunrise with you until the sunset of your life.

          總有一天,你會遇上那個人,陪你看每一次日出,直到你的人生落幕。


          每日掏心話

          每個人的心里,都有一個禁地,不愿再觸及,也不愿再想起,卻永遠無法忘記。既然忘不了,就不必費神忘記,做人本就很累,何必再自尋煩惱。

          來自:等你歸去來 | 責編:樂樂

          鏈接:cnblogs.com/yougewe/p/10327217.html

          程序員小樂(ID:study_tech)第 835 次推文 圖片來自百度


          往日回顧:手把手教你如何解決代碼中 if…else 過多的問題


          正文


          談到線上環境,一般開發同學,不太容易接觸到。即使接觸到,也只是其中的冰山一角!

          所以,其實說起線上環境的部署,咱們好像都有點懂,但是又都不一定完全懂!網上的知識無窮無盡,但往往都是各司一職,對于普通同學,很難窺其全貌!

          所以,我今天就來說說,一些普通的線上環境的部署步驟,和一些腳本小技巧吧。只希望通過這篇文章,能夠讓大家有一個運維的全局觀!

          我將會分幾條線來整理咱們的運維思路!

          一、從理論上講,我們應該怎么做?

          1.針對的是什么樣的用戶群體,體量大概會有多少?

          這是一個部署規劃的前題。為啥呢?

          一、如果你針對的是后臺管理員,人數也不多,那么你可能只需要一個服務器就可以了,前后端也都可以部署在同一臺服務器上;如果稍微考慮下單點故障問題,則頂多兩臺服務器搞定!

          二、如果針對的是前端普通用戶,那么,往往就會考慮多機部署,前后端分離,單點問題,負載均衡了;至于具體要部署多少臺,則要根據你的用戶情況來定了,當然,前期一般沒必要部署很多臺服務器!更多的考慮是橫向擴展的能力。只要能支持橫向擴展,則短期內,往往不用擔心性能和架構問題!

          2.為支持預估的用戶量,大概需要多少的帶寬?
            
          有訪問就會有流量產生,而預估的用戶量,則是一個帶寬資源需求的一個決斷依據!

          一般針對前期用戶不太確定的場景,可以先買個 10M 左右的共享帶寬,基本能夠應付;經過一段時間的觀察后,再進行帶寬的變更也可以;

          當然,考慮帶寬,自然也會存在一個公網IP的問題,因為流量是從IP進來的。而在IP之前,則是域名的訪問。域名問題則又涉及到DNS,不必細說!

          公網IP可以是直接指向機器的,也可以是指向負載均衡器的。如果想要支持橫向擴展,則IP的指向一定是一個負載均衡器。因為只有這樣,當遇到流量突增,或者做活動的時候,才能更快速的進行擴容!

          3.數據庫規劃如何?

          數據在當下時代,算是重中之重了。機器沒了可以再買,代碼沒了可以再寫,但是數據沒了就完蛋了!

          數據庫一般要遵從幾個基本原則: 一、帶寬要大;二、運算速度要快;三、要能承受足夠大的運算空間;(即:帶寬足夠大/cpu核數夠多/內存容量夠大/最大并發連接數/…)

          所以,一般不要在數據庫上省錢,能多點就多點!

          另外,也不要什么樣的數據都往數據庫(關系型數據庫)存,搞清楚各類型數據庫的強項與弱項,做出明智的選擇。否則會帶來很多不必要的麻煩!

          4.應用要基于操作系統來部署還是基于容器來部署?

          這是個決策性的問題!基于操作系統的部署,是一種比較傳統和常見的部署方式。優點是,很多系統工具都是完善的,只要你大概知道要部署什么,部署下來一般不會有太多問題,因為這是個完整的系統。

          但是,由于系統與系統之間可能不能完全一致,有各種各樣的差異,所以,你在這個機器上運行成功的東西,在另外的機器上則不一定能成功。因此,基于系統的部署將會使我們的問題排查難度大大增加,而且移值性會很差。比如你在機器A上安裝了10個軟件,你可能配置了n個選項,但是,當你在安裝B機器的時候,你并不能很好的利用原有的配置,你還得從頭一個個地來!

          因此,有另一個部署方案,基于容器的部署(我這里是基于docker容器的部署)。docker就類似于一個個的虛擬機,但是它更加輕量級,當一個docker部署好后,你可以任意復制到其他機器上運行,看起來很誘人吧。

          不過,docker只是入門級容器,對于大量集群容器的管理,還是顯得力不從心,當然你很容易找到另一個方案: Kubernetes (K8s); 你只要花上少許的時間了解下,你就可以應用了!

          當然了,使用容器的方案,有沒有什么缺點呢?應該是有的,比如本來可以基于系統的監控方案,因為接入容器后,監控指標則不一定適用了,當然現成的方案還是有的,不過得另外再花點時間研究了。再比如:如果容器出了問題,是否能排查出來,這也是另一個問題!

          5.都有些什么樣的基礎設施或者中間件?

          想要運行應用程序,自然是先考慮運行環境的。比如:應用需要 nginx 來做http服務器,用 tomcat 來做java web應用服務器,用redis來做緩存中間件,用zk來做應用協調中間件,用rabbitmq來做消息中間件,等等!

          因此,要在代碼跑起來之前,先要把這些環境給準備好咯。

          準備這些中間件或基礎設施之前,也要問下當下的形勢,是否有高性能高可用應用需求?比如:是否需要集群部署,或者單機部署?往往集群部署又會依賴其他的中間件!也更復雜!

          當然,這些都不是事。事兒是在出問題之后,能夠有意識,能夠猜測到問題發生的點!

          6.應用代碼應該怎樣部署?

          當基礎環境就緒后,就應該讓主角上場了。應用代碼怎么部署?

          最簡單的: 通過ftp上傳代碼到服務器上后,一個個部署!這種方案是最原始的,也是在沒有辦法搞更好的方案的時候使用的,不應長期使用;

          稍微好點的: 使用集成工具(如jenkins)進行打包,然后上傳一個私有yum鏡像服務器(yum 源)。然后在線進行yum 安裝;這種方式,借助了集成工具,幾個好處:


          • 可以檢測代碼合法性如:單元測試、代碼規范(可能需要插件);

          • 對任何的改動有簡單留檔,可以備查的同時,也為代碼的回滾提供了可能;

          • 減少了手動上傳導致的包破壞的可能性;

          • 適合大規模應用;


          再成熟點的: 再往后面,手動 yum 安裝也已經太累了,所以急需一個部署平臺,實現自動化部署;(這里的自動化部署可能就是基于CI集成部署的一種升級版)。總之,大大減小了人工參與程序,提升了效率,同時也保證了質量!當然,這種部署平臺已經經過了嚴格的測試,出錯的可能性也比較小了!

          7.服務器的安全性?

          不考慮服務器的安全性的應用,無異于自暴自棄。黑客無處不在,不過幸好現在系統也是越來越完善,只要稍加控制,即不那么容易被攻破了。但是如果放棄安全防護,則隨便來一個菜鳥程序員就把你搞死了,那時的損失就大了。推薦:如何設計一個安全的對外接口

          網絡安全是個很專業的領域,我不敢造次去談它。不過我們可以簡單的做下防護: 如防火墻、授權操作、病毒庫等等。當然,如果使用xx云服務,則輕松方便多了,在后臺點點設置幾下搞定!

          8.服務的可監控性?

          無監控,不上線!

          這是一個警示,如果線上服務沒有監控,則所有線上的東西,都成了盲區,這對程序員GG們來說,簡直太糟糕了,雖然他們很自信!

          監控分兩個方面:一是系統級別的監控;二是應用級別的監控;(一般忽略其他監控: 如網絡)

          系統級別的監控一般可以安裝第三方的軟件來解決: 如 zabbix, grafana …

          而應用級別的監控,則需要自己擁有一套監控代碼了,而這對初期項目,則往往比較吃力。當然,如果引入一些開源的解決方案也是可以的,比如 ELK, 做到分布式日志中心的作用的同時,也可以根據日志做相應的應用報錯監控!然而這又涉及另外的機器費用和人力成本問題,也顯得不那么簡單了。

          而如果使用xx云服務,則往往都會自帶服務器監控的,可以很方便地查看到服務器情況,站在高層次預估應用是否存在潛藏的問題!

          如上,就是一些個人覺得的在部署一整套線上環境的時候,需要考慮的事項!從理論上講解了下個人見解,不對之處,請賜教!

          二、接下來,我將給到一些實際的操作捷徑或提示?(linux)

          1.免密登錄服務器?

          在n服務器之間跳轉,如果每次都要求輸入密碼,那確實太煩了。尤其在密碼一般還很不容易記住的情況下!

          所以,可以將一臺服務器作為跳板機,在這臺服務器上,可以免密地登錄到允許的n臺子服務器;

          操作步驟有二:

          # 1. 先使用 ssh-keygen 生成本機的key
          ssh-keygen -t rsa # 如果已生成不要重復生成
          # 2. 使用 ssh-copy-id 將本機的 key 發送到需要免密登錄的服務器,首次copy時會要求輸入密碼,后續則免密了
          ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.1.2.111

          2.服務器之間文件(夾)拷貝?

          拷貝文件的目的有很多,比如:代碼同步,文件同步,資源同步,甚至是會話同步….

          # 1. 使用scp 拷貝文件
          scp /home/ol-web.war root@xxx.com:/www/tomcat/wepapps/ # 從本機拷貝到遠程
          scp /home/ol-web.war root@xxx.com:/www/tomcat/wepapps/ # 從遠程拷貝到本機
          scp -r /www/nginx/html/ root@.2.3.2:/www/nginx/html/ # 從本機拷貝文件夾到遠程
          # 2. 使用 rsync 同步文件,(可能需要安裝 rsync 服務)
          rsync -av --delete /www/nginx/html/ root@.2.3.1:/www/nginx/html/ # 同步所有屬性,本地刪除的文件也同步遠程刪除

          其中,scp一般是系統自帶的命令,而rsync則需要自行安裝服務。

          scp復制你可以認為是增量復制,所以遠程文件往往會越來越大,垃圾文件越來越多。

          而rsync則是保持兩端完全一致,可能會符合應用場景!但是,別忘了把rsync服務加入到開機啟動項中!

          3.快捷使用 ssh 等等命令,使用 tab 鍵進行信息補全?

          當使用 ssh / scp 等等命令操作的時候,其操作對象往往 1.2.3.x 這樣的ip顯示,如果不能友好點,那確實太累了!我們可以如下操作,以實現 ssh 也能更好的記憶:

          # 在文件 /root/.bashrc 中,添加腳本如下,使自動補全添加 ssh
          # auto complete ...
          complete -W "$(echo $(grep -v '^$|#' .ssh/config | sort -u | sed 's/^ssh //'))" ssh
          # 在文件 /root/.ssh/config 中,添加需要自動補全的服務器,
          Host 172.2.3.5 server-api-01
          Host 172.2.3.6 server-api-02
          # 以上服務器名字需要在 /etc/hosts 文件中添加相應解析
          # 而登錄 server時,只需, ssh server-api-01 即可

          如上補全工作,無需在所有服務器上進行操作,只需在相應的跳板機上提供功能即可!

          4.簡要 saltstack 搭建指南?

          salt 是個方便易用的集群管理工具,比如你可以用于批量重啟服務,全局搜索日志等等;

          # 1. 安裝, 僅需到相應機器上安裝即可
          yum install salt-master salt-minion
          # 2. 配置 /etc/salt/master /etc/salt/minion, 最簡單的,只需修改 minion 配置,指向 master 的ip即可;
          #指定master,冒號后有一個空格, minion
          master: 172.1.2.22
          id: server-api-01
          user: root
          # 3. 啟動所有節點, status, restart
          systemctl start salt-master # 162機器可用
          systemctl start salt-minion
          /etc/init.d/salt-master start # 155機器可用
          /etc/init.d/salt-minion start
          # 4. 將所有salt-minion 添加到 master 集群管理
          salt-key -A
          # 5. 登錄跳板機 api_01, 運行salt 操作,執行集群管理工作
          salt server-api-02 cmd.run 'lsof -i:80'
          salt '*' test.ping

          5.簡要集群復制shell腳本?

          有時,你可能需要將你的應用發布到n臺服務中,你可以直接改如下shell,也可以依賴于salt這樣的高級工具進行發布!shell 參考如下:

          #!/bin/bash
          # find out my ip to exclude...
          MY_MERCHINE_IP=`ifconfig eth0 |awk -F "[: ]+" '/inet addr/{print }'`;
          MERCHINE_IP_LIST="172.1.2.7 172.1.3.4";
          for m_ip in $MERCHINE_IP_LIST;
          do
          if [[ $m_ip !=$MY_MERCHINE_IP ]]; then
          echo "- Installing apps to mechine@${m_ip} ...";
          # install api apps
          scp /www/test/hello-1.0.0-SNAPSHOT.jar root@${m_ip}:/www/test/
          rsync -av --delete /www/html/ root@${m_ip}:/www/html/
          echo "- Install apps to merchine@${m_ip} done.";
          fi;
          done;

          6.簡要docker搭建指南?

          docker 作為一個容器化的基石,一出世就被追棒。包括現在的 k8s ,也是基于docker的。docker 可以讓你在一處搭建,處處運行,從而避免每次新買機器就要搞很久的尷尬局面;其搭建也是很簡單的(簡單應用):

          為方便任意發揮,我們可以基于centos這種系統級別的鏡像進行創建自己的image;

          # docker 安裝:
          yum install docker
          service docker start
          # 拉取 centos6 的 docker 鏡像
          docker pull centos:6
          docker images
          # 構建一個 image, 創建空目錄,編輯 Dockerfile
          vim Dockerfile # 內容可變
          FROM centos:6
          MAINTAINER oom <w@163.com>
          # move all configuration files into container

          # RUN yum install -y lsof
          # EXPOSE 80
          # CMD ["sh","-c","service httpd start;bash"]
          # 創建鏡像
          docker build -t tmp_image:1.0 .
          # 創建并運行容器
          docker run -h tmp_container -itd --name tmp_container -v /opt/docker/webapps:/www/webapp tmp_image:1.0
          # 進入容器,相當于進入 centos 操作系統
          docker exec -it tmp_container bash
          # 保存容器修改到images
            docker commit -m 'web final.' 49d79fc19eaa tmp_image:1.2
          # 備份容器修改后的docker鏡像
            docker save > /opt/images/images_final/tmp_image.final.tar tmp_image:1.2
          # 恢復你的備份鏡像,即全網發布
          # 可以在任何裝 docker 的地方加載保存的鏡像
            docker load -i /opt/images/images_final/tmp_image.final.tar

          7.定制你的登錄歡迎語?

          由于可能存在線上環境與測試環境共存的情況,一不小心的切換錯誤,就可能導致不可挽回的損失。所以,如果我們能在登錄的時候,做一個簡單的提示,那么就會少一點出錯的可能性。所以,訂制你的登錄歡迎語吧!

          # 修改登錄歡迎語 vim /etc/motd
          *****************************************************************
          !!! WARNING: 歡迎來到線上機器: service-api-01 ,請謹慎操作哦 !!!
          *****************************************************************

          這樣,用戶登錄后,就會清楚的知道自己是在操作生產環境了!

          8.更方便的查看nginx的訪問日志?

          對于后端的日志而言,往往都是主動打印到某個固定位置,從而開發人員可以直接使用 tail -f xxx.log 進行日志的查看!

          然而對于前端的代碼而言,則往往沒有相應的開發日志,唯一可以借助的就是 http 服務器的日志來排查問題了!

          所以,比如使用 nginx 作為 http 服務器,那么就應該把盡可能多的有用日志打印出來。那么,如何快速查看 nginx 日志,則是有必要的!比如我們可以這樣:

          # vim /usr/bin/log_nginx_host , 使用 log_nginx_host 直接查看所有 nginx 日志
          tail -f /var/log/nginx/access.log /var/log/nginx/error.log

          如上,將會把訪問日志與錯誤日志一起打印出來,從而快速定位問題!


          歡迎在留言區留下你的觀點,一起討論提高。如果今天的文章讓你有新的啟發,學習能力的提升上有新的認識,歡迎轉發分享給更多人。


          猜你還想看


          阿里、騰訊、百度、華為、京東最新面試題匯集

          從上帝視角看Java如何運行

          一次項目代碼重構:使用Spring容器干掉條件判斷

          IDEA-2020.1 版本針對調試器和代碼分析器的改進,值得期待

          關注訂閱號「程序員小樂」,收看更多精彩內容
          嘿,你在看嗎?

          數創建與定義的過程

          • 函數定義階段 在堆內存中開辟一段空間 把函數體內的代碼一模一樣的存儲在這段空間內 把空間賦值給棧內存的變量中
          • 函數調用階段 按照變量名內的存儲地址找到堆內存中對應的存儲空間 在調用棧中開辟一個新的函數執行空間 在執行空間中進行形參賦值 在執行空間中進行預解析 在執行空間中完整執行一遍函數內的代碼 銷毀在調用棧創建的執行空間

          不會銷毀的函數執行空間

          1. 當函數內返回一個引用數據類型
          2. 并且函數外部有變量接收這個引用數據類型
          3. 函數執行完畢的執行空間不會銷毀
          4. 如果后續不需要這個空間了,只要讓變量指向別的位置即可
          function fn() {
              const obj={
                  a: 1,
                  b: 2
              }
              return obj
          }
          
          const res=fn()
          console.log(res)
          
          // 如果后續不需要這個空間了, 只需要讓 res 指向別的位置即可
          res=100
          


          閉包

          • 需要一個不會被銷毀的執行空間
          • 需要直接或間接返回一個函數
          • 內部函數使用外部函數的私有變量
          • 概念 : 函數里的函數
          • 優點: 可以在函數外訪問函數內的變量 延長了變量的生命周期
          • 缺點: 閉包函數不會銷毀空間,大量使用會造成內存溢出
          function outer () {
              let a=100
              let b=200
          
              // 我們說 inner 是 outer 的閉包函數
              function inner () {
                  /**
                   * 我使用了一個 a 變量, 但是 inner 自己沒有
                   * 所以我用的是 外部函數 outer 內部的變量 a
                  */
                  // console.log(a)
                  return a
              }
              return inner
          }
          
          // 我們說 res 是 outer 的閉包函數
          let res=outer()
          
          let outerA=res()
          console.log(outerA)
          


          沙箱模式

          • 利用了函數內間接返回了一個函數
          • 外部函數返回一個對象,對象內書寫多個函數
          function outer () {
              let a=100
              let b=200
          
              // 創建一個 沙箱, "間接的返回一個函數"
              const obj={
                  getA: function () {
                      return a
                  },
                  getB: function () {
                      return b
                  },
                  setA: function (val) {
                      a=val
                  }
              }
              return obj
          }
          
          // 得到一個沙箱
          const res1=outer()
          
          console.log(res1.getA())    // 100
          console.log(res1.getB())    // 200
          
          res1.setA(999)
          console.log(res1.getA())    // 999
          
          // 重新得到一個沙箱
          const res2=outer()
          console.log(res2.getA())    // 100
          


          沙箱小案例

          <button class="sub">-</button>
          <input class="inp" type="text" value="1">
          <button class="add">+</button>
          <br>
          <button class="sub1">-</button>
          <input class="inp1" type="text" value="1">
          <button class="add1">+</button>
          


          // 準備一個沙箱
          function outer() {
              let a=1
              return {
                  getA() {
                      return a
                  },
                  setA(val) {
                      a=val
                  }
              }
          }
          
          // 0. 獲取元素
          const subBtn=document.querySelector('.sub')
          const addBtn=document.querySelector('.add')
          const inp=document.querySelector('.inp')
          
          // 0. 準備變量
          // let count=1
          let res=outer()
          subBtn.onclick=function () {
              let count=res.getA()
              res.setA(count - 1)
              inp.value=res.getA()
          }
          addBtn.onclick=function () {
              // count++
              let count=res.getA()
              res.setA(count + 1)
              inp.value=res.getA()
          }
          
          // 0. 獲取元素
          const subBtn1=document.querySelector('.sub1')
          const addBtn1=document.querySelector('.add1')
          const inp1=document.querySelector('.inp1')
          
          // 0. 準備變量
          let res1=outer()
          subBtn1.onclick=function () {
              let count=res1.getA()
              res1.setA(count - 1)
              inp1.value=res1.getA()
          }
          addBtn1.onclick=function () {
              let count=res1.getA()
              res1.setA(count + 1)
              inp1.value=res1.getA()
          }
          


          沙箱語法糖

          • 盡可能的簡化沙箱模式的語法
          • 利用 get 和 set 進行操作數據
          • 語法糖: 在不影響功能的情況下提供一點更適合操作的語法
          function outer() {
              let a=100
              let b=200
          
              return {
                  get a() { return a },
                  get b() { return b },
                  set a(val) { a=val }
              }
          }
          
          let res=outer()
          console.log(res.a)
          console.log(res.b)
          res.a=999
          console.log(res.a)   // 999 
          


          閉包面試題!!!!

          function fun(n, o) {
              console.log(o)
          
              const obj={
                  fun: function (m) {
                      return fun(m, n)
                  }
              }
          
              return obj
          }
          
          var a=fun(0)    // undefined
          a.fun(1)    // 0
          a.fun(2)    // 0
          a.fun(3)    // 0
          
          /**
           *  var a=fun(0)
           *  a.fun(1)
           *  a.fun(2)
           *  a.fun(3)
           *
           *  1. var a=fun(0)
           *          調用 fun(QF001) 函數(QF001) 傳遞一個 參數 0
           *              全局函數 fun (QF001) 的 形參 n==0     形參 o==undefined
           *          調用 fun 函數后, 會返回一個對象 存儲在 變量 a 中, 這個對象內部有一個屬性叫做 fun, 屬性值為 一個函數(QF002),
           *              所以我們可以通過 a.fun()   去調用這個函數
           *
           *  2. a.fun(1)
           *      2.1 調用這個函數 會 return 一個函數 fun (為全局函數 QF001) 的調用結果,   
           *      2.2 調用全局函數 fun(m, n)       m 此時 傳遞的是 1, n 傳遞的是 0
           *      2.3 執行全局函數 fun(m, n) 內部會輸出第二個形參
           *
           *  3. a.fun(2)
           *      2.1 調用這個函數 會 return 一個函數 fun(為全局函數 QF001) 的調用結果
           *      2.2 調用全局函數 fun(m, n)  m 此時傳遞的是 2, n 傳遞的是 0
           *      2.3 執行全局函數 fun(m, n) 內部會輸出第二個形參
           *
          */
          


          防抖與節流

          防抖

          • 解釋:在短時間內觸發一件事,每次都用上一次的時間替代,也就是只執行最后一次
           

          主站蜘蛛池模板: 亚洲AV无码一区二区三区牲色| 一区二区和激情视频| 无码人妻精品一区二区蜜桃百度| 亚洲一区动漫卡通在线播放| 久久se精品一区二区影院| 亚洲国产激情一区二区三区| 一区二区三区高清视频在线观看| 日韩精品国产一区| 国产午夜精品一区二区三区不卡| 亚洲国产成人精品久久久国产成人一区二区三区综 | AV无码精品一区二区三区宅噜噜 | 国模一区二区三区| 精品人妻一区二区三区四区在线 | 国产在线aaa片一区二区99| 在线精品视频一区二区| 日本精品一区二区三本中文| 国产一区二区三区在线2021| 日韩在线视频一区二区三区| 制服中文字幕一区二区| 大香伊蕉日本一区二区| 国产精品揄拍一区二区久久| 无码人妻久久一区二区三区免费| 精品深夜AV无码一区二区| 国产精品综合AV一区二区国产馆 | 国产高清视频一区二区| 久久久久久综合一区中文字幕 | 国产福利精品一区二区| 好湿好大硬得深一点动态图91精品福利一区二区 | 无码乱人伦一区二区亚洲| 久久se精品一区精品二区国产| 国语对白一区二区三区| 国精产品一区一区三区有限公司 | 日韩社区一区二区三区| 日韩精品一区二区三区毛片| 精品人妻无码一区二区色欲产成人| 久久一本一区二区三区| 日本不卡一区二区三区视频| 在线观看日本亚洲一区| 性色av无码免费一区二区三区| 亚洲国产成人精品无码一区二区| 国产suv精品一区二区33|