整合營銷服務商

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

          免費咨詢熱線:

          JavaScript-第四章

          、什么是面向對象?

          面向對象僅僅是一個概念或者編程思想

          通過一種叫做原型的方式來實現面向對象編程

          1、 創建對象(自定義對象,內置對象)

          基于Object對象的方式創建對象-自定義對象

          示例:

          var 對象名稱=new Object( );

          var flower=new Object();

          flower.name="長春花";

          flower.genera="夾竹桃科 長春花屬";

          flower.area="非洲、亞熱帶、熱帶以及中國大陸的華東、西南、中南等地";

          flower.uses="觀賞或用藥等";

          flower.showName=function(){ alert(this.name); }

          flower.showName();


          常見的內置對象

          String(字符串)對象

          Date(日期)對象

          Array(數組)對象

          Boolean(邏輯)對象

          Math(算數)對象

          RegExp對象


          二、

          如何解決使用同一個接口不需要創建很多對象,減少產生大量的重復代碼?

          1、構造函數:

          function Flower(name,genera,area,uses){

          this.name=name;

          …….

          this.showName=function(){

          alert(this.name);

          }

          }

          var flower1=new Flower("長春花","夾竹桃科 長春花屬","非洲、亞熱帶、熱帶以及中國大陸的華東、西南、中南等地","觀賞或用藥等")

          flower1.showName();

          2、原型對象:

          function Flower(){


          }

          Flower.prototype.name="曼陀羅花";

          Flower.prototype.genera="茄科 曼陀羅屬";

          Flower.prototype.area="印度、中國北部";

          Flower.prototype.uses="觀賞或藥用";

          Flower.prototype.showName=function() {

          alert(this.name);

          }

          var flower1=new Flower();

          flower1.showName();

          var flower2=new Flower();

          flower2.showName();

          alert(flower1.showName==flower2.showName);

          三、繼承

          1.原型鏈:一個原型對象是另一個原型對象的實例

          相關的原型對象層層遞進,就構成了實例與原型的鏈條,就是原型鏈

          示例:

          function Humans(){

          this.foot=2;

          }

          Humans.prototype.getFoot=function(){

          return this.foot;

          }

          function Man(){

          this.head=1;

          }

          Man.prototype=new Humans(); //繼承了Humans

          Man.prototype.getHead=function(){

          return this.head;

          }

          var man1=new Man();

          alert(man1.getFoot()); //2

          alert(man1 instanceof Object); //true

          alert(man1 instanceof Humans); //true

          alert(man1 instanceof Man); //true

          2.對象繼承:

          function Humans(){

          this.clothing=["trousers","dress","jacket"];

          }

          function Man(){ }

          //繼承了Humans

          Man.prototype=new Humans();

          var man1=new Man();

          man1.clothing.push("coat");

          alert(man1.clothing);

          var man2=new Man();

          alert(man2.clothing);

          3.組合繼承:

          組合繼承:有時也叫做偽經典繼承

          將原型鏈和借用構造函數的技術組合到一塊,發揮二者之長的一種繼承模式

          使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承


          四、這一章的示例代碼:

          <html>


          <head>

          <title>面向對象標題欄替換和修改</title>

          </head>

          <style>

          * {

          margin: 0;

          padding: 0;

          }


          ul li {

          list-style: none;

          }


          main {

          width: 960px;

          height: 500px;

          border-radius: 10px;

          margin: 50px auto;

          }


          main h4 {

          height: 100px;

          line-height: 100px;

          text-align: center;

          }


          .tabsbox {

          width: 900px;

          margin: 0 auto;

          height: 400px;

          border: 1px solid lightsalmon;

          position: relative;

          }


          nav ul {

          overflow: hidden;

          }


          nav ul li {

          float: left;

          width: 100px;

          height: 50px;

          line-height: 50px;

          text-align: center;

          border-right: 1px solid #ccc;

          position: relative;

          }


          nav ul li.liactive {

          border-bottom: 2px solid #fff;

          z-index: 9;

          }


          #tab input {

          width: 80%;

          height: 60%;

          }


          nav ul li span:last-child {

          position: absolute;

          user-select: none;

          font-size: 12px;

          top: -18px;

          right: 0;

          display: inline-block;

          height: 20px;

          }


          .tabadd {

          position: absolute;

          /* width: 100px; */

          top: 0;

          right: 0;

          }


          .tabadd span {

          display: block;

          width: 20px;

          height: 20px;

          line-height: 20px;

          text-align: center;

          border: 1px solid #ccc;

          float: right;

          margin: 10px;

          user-select: none;

          }


          .tabscon {

          width: 100%;

          height: 300px;

          position: absolute;

          padding: 30px;

          top: 50px;

          left: 0px;

          box-sizing: border-box;

          border-top: 1px solid #ccc;

          }


          .tabscon section,

          .tabscon section.conactive {

          display: none;

          width: 100%;

          height: 100%;

          }


          .tabscon section.conactive {

          display: block;

          }

          </style>


          <body>

          <main>

          <h4>

          JS面向對象 動態添加標簽頁

          </h4>

          <div class="tabsbox" id="tab">

          <!-- tab標簽 -->

          <nav class="fisrstnav">

          <ul>

          <li class="liactive"><span>測試1</span><span class="iconfont icon-guanbi"></span> </li>

          <li><span>測試2</span><span class="iconfont icon-guanbi"></span> </li>

          <li class="liactive"><span>測試3</span><span class="iconfont icon-guanbi"></span> </li>

          </ul>

          <div class="tabadd">

          <span>+</span>

          </div>

          </nav>

          <!-- tab內容 -->

          <div class="tabscon">

          <section class="conactive">測試1</section>

          <section>測試2</section>

          <section>測試3</section>

          </div>

          </div>

          </main>

          </body>

          <script>

          var that;

          class Tab {

          constructor(id) {

          // 獲取元素

          that = this;

          this.main = document.querySelector(id);

          this.add = this.main.querySelector('.tabadd');

          // li的父元素

          this.ul = this.main.querySelector('.fisrstnav ul:first-child');

          // section 父元素

          this.fsection = this.main.querySelector('.tabscon');

          this.init();

          }

          init() {

          this.updateNode();

          // init 初始化操作讓相關的元素綁定事件

          this.add.onclick = this.addTab;

          for (var i = 0; i < this.lis.length; i++) {

          this.lis[i].index = i;

          this.lis[i].onclick = this.toggleTab;

          this.remove[i].onclick = this.removeTab;

          this.spans[i].ondblclick = this.editTab;

          this.sections[i].ondblclick = this.editTab;


          }

          }

          // 因為我們動態添加元素 需要從新獲取對應的元素

          updateNode() {

          this.lis = this.main.querySelectorAll('li');

          this.sections = this.main.querySelectorAll('section');

          this.remove = this.main.querySelectorAll('.icon-guanbi');

          this.spans = this.main.querySelectorAll('.fisrstnav li span:first-child');

          }

          // 1. 切換功能

          toggleTab() {

          // console.log(this.index);

          that.clearClass();

          this.className = 'liactive';

          that.sections[this.index].className = 'conactive';

          }

          // 清除所有li 和section 的類

          clearClass() {

          for (var i = 0; i < this.lis.length; i++) {

          this.lis[i].className = '';

          this.sections[i].className = '';

          }

          }

          // 2. 添加功能

          addTab() {

          that.clearClass();

          // (1) 創建li元素和section元素

          var random = Math.random();

          var li = '<li class="liactive"><span>新選項卡</span><span class="iconfont icon-guanbi"></span></li>';

          var section = '<section class="conactive">測試 ' + random + '</section>';

          // (2) 把這兩個元素追加到對應的父元素里面

          that.ul.insertAdjacentHTML('beforeend', li);

          that.fsection.insertAdjacentHTML('beforeend', section);

          that.init();

          }

          // 3. 刪除功能

          removeTab(e) {

          e.stopPropagation(); // 阻止冒泡 防止觸發li 的切換點擊事件

          var index = this.parentNode.index;

          console.log(index);

          // 根據索引號刪除對應的li 和section remove()方法可以直接刪除指定的元素

          that.lis[index].remove();

          that.sections[index].remove();

          that.init();

          // 當我們刪除的不是選中狀態的li 的時候,原來的選中狀態li保持不變

          if (document.querySelector('.liactive')) return;

          // 當我們刪除了選中狀態的這個li 的時候, 讓它的前一個li 處于選定狀態

          index--;

          // 手動調用我們的點擊事件 不需要鼠標觸發

          that.lis[index] && that.lis[index].click();

          }

          // 4. 修改功能

          editTab() {

          var str = this.innerHTML;

          // 雙擊禁止選定文字

          window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

          // alert(11);

          this.innerHTML = '<input type="text" />';

          var input = this.children[0];

          input.value = str;

          input.select(); // 文本框里面的文字處于選定狀態

          // 當我們離開文本框就把文本框里面的值給span

          input.onblur = function () {

          this.parentNode.innerHTML = this.value;

          };

          // 按下回車也可以把文本框里面的值給span

          input.onkeyup = function (e) {

          if (e.keyCode === 13) {

          // 手動調用表單失去焦點事件 不需要鼠標離開操作

          this.blur();

          }

          }

          }


          }

          new Tab('#tab');

          </script>


          </html>

          ava 內存模型中的 happen-before 是什么?

          Happen-before 關系,是Java 內存模型中保證多線程可見性的機制,也是早期語言規范中含糊可見性概念的一個精確定義。

          它的具體表現形式,包括但遠不止 synchronized,volatile,lock 操作順序等方面。

          happen-before 原則

          • 程序順序規則:一個線程內執行的每個操作,都保證 happen-before 后面的操作,這樣就保證了程序順序規則,
          • volatile 變量規則:對于 volatile 變量,對他的寫操作,保證 happen-before 在隨后對改變量的讀取操作。
          • 監視器鎖規則:對于一個鎖的解鎖操作,保證 happen-before 加鎖操作。
          • 線程啟動 happen-before 規則:Thread 對象的 start() 方法先行于此線程的每一個動作
          • 線程中斷 happen-before 規則:對線程 interrupt() 方法的調用先行發生于被中斷線程的代碼檢測到中斷事件的發生。
          • 線程終結規則:假定線程A在執行的過程中,通過制定ThreadB.join()等待線程B終止,那么線程B在終止之前對共享變量的修改在線程A等待返回后可見。
          • 對象終結規則,一個對象的初始化完成happen-before 于 finalizer() 方法的開始
          • 傳遞性:happen-before 存在傳遞性,a happen-before b ,b happen-before c ,那么 a happen-before c 。

          happen-before 保障了順序執行,也包括了內存讀寫的操作順序。

          happen-before 與 JMM 的關系

          image

          如何學習 Java 內存模型(JMM)

          JMM 可以看作是深入理解Java并發編程、編譯器和JM內部機制的必要條件,但這同時也是個容易讓初學者無所適從的主題。

          • 明確目的,建議不要一頭扎進各種CPU體系結構,糾結于不同的緩存、流水線、執行單元等。這些東西雖然很酷,但其復雜性是超乎想象的,很可能會無謂增加學習難度,也未必有實踐價值。
          • 克制住對”秘籍"的誘惑。有些時候,某些編程方式看起來能起到特定效果,但分不清是實現差異導致的表現,還是"規范″要求的行為,就不要依賴于這種"表現"去編程,盡量遵循語言規范進行,這樣我們的應用行為才能更加可靠、可預計。

          JMM 可以解決什么問題?

          簡化多線程編程,保證程序可移植性

          Java 是最早嘗試提供內存模型的語言,可簡化多線程編程,保障程序可移植。 早期的 C/C++ 不存在內存模型的概念,依賴處理器本身的內存一致性模型。 但是不同的處理器差異比較大,不能保證 C++ 程序在處理器A 可以運行,在處理器B 上也可以運行。

          • https://en.wikipedia.org/wiki/Memory_ordering

          對指令重排序提供清晰的規范

          過于范范的內存模型定義,有很多模棱兩可之處,對 synchronized 或者 volatile 產生的指令重排序問題,如果沒有清晰的規范,不能保證一些多線程程序的正確性。

          所以,Java迫切需要一個完善的JMM,能夠讓普通Java開發者和編譯器、JVM工程師,能夠淸地達成共識。換句話說,可以相對簡單并準確地判斷岀,多線程程序什么樣的執行序列是符合規范的。

          JVM 開發者

          對于編譯器、JVM開發者,關注點可能是如何使用類似內存屏( Memory-Barrier)之類技術,保證執行結果符合JMM的推斷。

          Java 應用工程師

          對于Java應用開發者,則可能更加關注 volatile、 synchronized等語義,如何利用類{ happen- before的規則,寫出可靠的多線程應用。

          image

          Java 內存模型的抽象定義

          包含本地內存和主內存的定義

          JMM 是怎么解決可見性的問題

          image

          JMM 內部是怎樣實現 happen-before 原則的?

          • 內存屏障
          • 禁止重排序

          以 volatile 變量為例:

          • 對改變量的寫操作之后,編譯器插入一個寫屏障
          • 對改變量的讀操作之前,編譯器會插入一個讀屏障

          內存屏障能夠在類似變量讀、寫操作之后,保證其他線程對 volatile變量的修改對當前線程可見,或者本地修改對其他線程提倛可見性。換句話說,線程寫入,寫屏障會通過類似強迫刷出處理器緩存的方式,讓其他線程能夠拿到最新數值

          如果你對更多內存屏障的細節感興趣,或者想了解不同體系結構的處理器模型,建議參考JSR-133相關文檔,我個人認為這些都是和特定硬件相關的,內存屏障之類只是實現JMM規范的技術手段,并不是規范的要求。

          • http://gee.cs.oswego.edu/dl/jmm/cookbook.html
          class VolatileExample {
          int  a = 0;
          volatile boolean flag= false;
          public void writer(){
             a=1;        // 1
             flag = true; //2
          } 
          public void reader(){
            if(flag){  //3
              int i = a ;//4
              ...
            }
          } 
          

          假設線程A執行 writer方法之后,線程B執行 reader0方法。根據 happens-before規則,這個過程建立的 happens-before關系可以分為3類:

          1. 根據程序次序規則,1 happens-before2;3 happens-before4。
          2. 根據 volatile 規則,2 happens-before3
          3. 根據 happens-before的傳遞性規則,1 happens-before4。

          上述 happens-before關系的圖形化表現形式如下:

          image

          在上圖中,每一個箭頭鏈接的兩個節點,代表了一個 happens-before關系。黑色箭頭表示程序順序規則;橙色箭頭表示 volatile規則;藍色箭頭表示組合這些規則后提供的 happens-before保證。 最終讀取到的i 就是 1 。

          image

          線程A在寫flag變量后,本地內存A中被線程A更新過的兩個共享變量的值被刷新到主內存中。此時,本地內存A和主內存中的共享變量的值是一致的。

          當讀一個 volatile變量時,JMM會把該線程對應的本地內存置為無效。線程接下來將從主內存中讀取共享變量。如圖所示,在讀flag變量后,本地內存B包含的值已經被置為無效。此時,線程B必須從主內存中讀取共享變量。線程B的讀取操作將導致本地內存B與主內存中的共享變量的值變成一致。

          image

          • 線程A寫一個 volatile變量,實質上是線程A向接下來將要讀這個 volatile變量的某個線程發出了(其對共享變量所做修改的)消息
          • 線程B讀一個 volatile變量,實質上是線程B接收了之前某個線程發出的(在寫這個volatile變量之前對共享變量所做修改的)消息
          • 線程A寫一個 volatile變量,隨后線程B讀這個 volatile變量,這個過程實質上是線程A通過主內存向線程B發送消息。

          有序性,原子性,可見性是線程安全的基本保障。

          volatile 使用了內存屏障實現可見性

          • 在每個 volatile寫操作的前面插入一個Storestore屏障。
          • 在每個 volatile寫操作的后面插入一個Storeload屏障。
          • 在每個 volatile讀操作的后面插入一個Loadload屏障。
          • 在每個 volatile讀操作的后面插入一個Loadstore屏障。

          image

          我們經常會說 volatile b比synchronized之類更加輕量,但輕量也僅僅是相對的, volatile的讀、寫仍然要比普通的讀寫要開銷更大,所以如果你是在性能高度敏感的場景,除非你確定需要它的語義,不然慎用。

          程序員開發者社區

          近因為一些網頁的需要,需要比較深入的使用了CSS 的「偽元素」( Pseudo Element ),發現原來不只是用用before或after 而已,可以玩的東西還真是不少,所以就來篇文章,把這些比較不常玩的用法歸納整理下,希望對你的日常工作有所幫助。

          什么是「偽元素」?

          「偽元素」之所以稱作「偽」,除了英文從「Pseudo」翻譯過來之外,就是因為它并不是真正網頁里的元素,但行為與表現又和真正網頁元素一樣,也可以對其使用CSS 操控。

          跟偽元素類似的還有「偽類」( Pseudo classes ),在W3C的定義里總共有五個偽元素(其他仍在測試階段),分別是::before、::after、::first-line、::first-letter和::selection,為了和偽類區分,偽元素使用兩個冒號「::」開頭,而偽類使用一個冒號「:」開頭(像是:hover、:target...等)。

          雖然現在的瀏覽器就算寫一個冒號也可以正常運作,不過為了方便區分,用兩個冒號還是比較好的,而且不論瀏覽器是什么,::selection必須是兩個冒號才能正常運作。

          參考:MDN Pseudo-elements、偽類child和of-type

          認識::before 與::after

          ::before、::after大概是最常使用的偽元素,兩者都是以display:inline-block的屬性存在,::before是在原本的元素「之前」加入內容,::after則是在原本的元素「之后」加入內容,同時偽元素也會「繼承」原本元素的屬性,如果原本文字是黑色,偽元素的文字也會是黑色。

          舉例來說,下面這段程式碼,有一個div 內容是「大家好,我是div」,使用::before、::after 之后,會在原本div 的前后各添加一段文字,并且讓這兩段文字都呈現紅色。

          div::before{
           content:"我是 before";
           color:red;
          }
          div::after{
           content:"我是 after";
           color:red;
          }
          

          實用的content

          上述的內容乍看之下很容易理解,比較需要注意的是一定要具備content的屬性,就算是只有content:"";都可以,因為沒有content的偽元素是不會出現在畫面上的,然而content是個很特別的屬性,它可以使用attr直接獲取內容元素的屬性值( attribute ),舉例來說,在HTML里有一個超連結,點擊后會彈出新視窗并連結至Google:

          <a  target="_blank">google</a>
          

          使用下列的程式碼用法,將會把超連結的href 內容與target 內容,透過偽元素一前一后的顯示出來。

          a::before{
           content: attr(href);
           color:red;
          }
          a::after{
           content: attr(target);
           color:green;
          }
          

          此外content內容是可以「相加」的,不過用法不像JavaScript使用+號來相連,而是直接用一個空白鍵就可以不斷的累加下去,以下面的程式碼來說,可以在剛剛擷取的超連結文字后方和target屬性前方,加入標點符號。

          a::before{
           content: "( " attr(href) " ) < ";
           color:red;
          }
          a::after{
           content: " > ( " attr(target) " ) ";
           color:green;
          }
          

          content 甚至可以使用url 放入圖片的功能,下列的程式碼會呈現出三張圖片。

          div::before{
           content:url(圖片網址) url(圖片網址) url(圖片網址);
          }
          

          通過調整border的屬性,我們可以實現上下左右的三角形,再結合偽元素before,after,content可以繪制多種多邊形,筆者在這篇文章有過介紹,感興趣的可以看看 :只用1個div,你能用CSS繪制:正3、4、5、6、7、8邊形嗎?

          content搭配quotes使用

          在CSS里有個不常用的屬性就是quotes,這是做為定義「括號格式」的屬性,也就是如果在一段文字被包住,這段文字的前后就會出現自定義的標簽替換(可以是括號、特殊符合、文字等),而且quotes支持多層嵌套,也就是你可以一層層的寫下去,以下面這段HTML文字舉例:

          最外層<q>第一層<q>第二層</q><q>第二層<q>第三層</q></q></q>
          

          quotes 的屬性如果只寫一層,就會看到只出現一種括號,前后括號使用空白分隔,兩組為一個單位,前后可以不同符號。

          q{
           quotes: ' < ' ' > ';
          }
          

          如果寫了三層,就會看到出現三種括號,也會把文字當作括號使用。

          q{
           quotes: ' < ' ' > ' ' ya ' ' ya ' ' ( ' ' ) ' ;
          }
          

          (請注意開合標簽的就近分配原則)

          同樣的道理,我們可以應用在content里面,而且通過偽元素::before和::after處于前后的預設位置,甚至不用就實現前后括號的效果,以下面這段HTML文字舉例,把剛剛的q全部換成span:

          最外層<span>第一層<span>第二層</span><span>第二層<span>第三層</span></span></span>
          

          CSS的部分比較特別,在偽元素content里使用了open-quote (啟始括號)和close-quote (結束括號)這兩個有趣的值,換句話說open-quote對應到,close-quote對應到,此外也由于括號是在偽元素內,就可以指定不同的顏色或樣式了。

          span{
           quotes: ' < ' ' > ' ' ya ' ' ya ' ' ( ' ' ) ' ;
          }
          span::before{
           content:open-quote;
           color:red;
          }
          span::after{
           content:close-quote;
           color:#aaa;
          }
          

          文章來源:https://www.oxxostudio.tw/articles/201706/pseudo-element-1.html

          原文作者:oxxostudio

          由于網頁為繁體內容,術語描述和標點話術的差異的問題,筆者在保證不改變原意的基礎上做了調整,并且內容頁進行了驗證確認無誤,歡迎大家指正。

          小結

          雖然說偽元素很好用,但偽元素的內容實際上不存在網頁里( 如果打開瀏覽器的開發者工具,是看不到內容的),所以如果在里頭塞了太多的重要的內容,反而會影響到SEO 的成效,因此對于使用偽元素的定位,還是當作「輔助」性質會比較恰當。


          主站蜘蛛池模板: 日韩精品乱码AV一区二区| 日本韩国黄色一区二区三区| 亚洲av一综合av一区| 亚洲综合在线成人一区| 国产在线一区二区在线视频| 国模精品一区二区三区视频| 老熟女五十路乱子交尾中出一区| 一区二区三区四区在线观看视频| 亚洲a∨无码一区二区| 91一区二区三区四区五区 | 91在线一区二区| 风间由美性色一区二区三区| 久久影院亚洲一区| 白丝爆浆18禁一区二区三区 | 国产乱码精品一区二区三区四川人 | 色国产精品一区在线观看| 国产精品亚洲一区二区三区在线| 亚洲一区无码精品色| 亚洲一区日韩高清中文字幕亚洲| 国产精品男男视频一区二区三区| 精品乱码一区内射人妻无码| 国产成人免费一区二区三区| 国内精自品线一区91| 色一情一乱一伦一区二区三欧美| 亚洲一区精彩视频| 国内精品一区二区三区最新| 在线观看一区二区三区视频| 影院成人区精品一区二区婷婷丽春院影视| 国产精品视频一区麻豆| 午夜一区二区免费视频| 日本中文字幕在线视频一区| 一区二区三区亚洲视频| 日韩综合无码一区二区| 国产福利精品一区二区| 麻豆亚洲av熟女国产一区二| 蜜臀AV无码一区二区三区| 高清一区二区三区视频| 中文字幕一区二区免费| 人妻久久久一区二区三区| 亚洲AV无码一区二区三区性色| 亚洲日韩AV无码一区二区三区人|