沐鳴測速註冊_Js如何動態修改css樣式

如何動態修改css樣式

一、使用obj.className來修改樣式表的類名

function changeStyle1() {
  var obj = document.getElementById("btnB");
  obj.style.backgroundColor= "black";
}

缺點:會覆蓋原有的style

二、使用obj.style.cssTest來修改嵌入式的css

function changeStyle2() {
   var obj = document.getElementById("btnB");
   obj.style.cssText = " display:block;color:White;
}

缺點:會覆蓋原有的style

三、使用obj.className來修改樣式表的類名

function changeStyle3() {
  var obj = document.getElementById("btnB");
  //obj.className = "style2";
  obj.setAttribute("class", "style2");
}

優點:不會覆蓋

四、使用更改外聯的css文件,從而改變元素的css

<link href="css1.css" rel="stylesheet" type="text/css" id="css"/>
function changeStyle4() {
   var obj = document.getElementById("css");
   obj.setAttribute("href","css2.css");
 }

實現整體頁面換膚的最佳方案

五、通過js更新這個元素的class屬性

function addClass(element,value) {
    if (!element.className) {
        element.className = value;
    } else {
        newClassName = element.className;
        newClassName += " "; //這句代碼追加的類名分開
        newClassName += value;
        element.className = newClassName;
    }
}

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9445

沐鳴登錄平台_程序員如何提高開發技能?

你只在早上9點至晚上5點間編碼,卻擔心這樣不夠好嗎?你看見其他的程序員工作於個人項目或開源項目,參与編程馬拉松,並花費所有的業餘時間編寫軟件了嗎?你可能會認為只在自己的工作時間編碼,只朝九晚五地編寫軟件,將永遠不會非常優異。你可能認為,只有那些連吃飯、睡覺和呼吸間都在編碼的人才能脫穎而出。但實際上堅持一周40小時的工作時間依然可以讓你成為一個有價值的、熟練的程序員。

工作於個人或開源軟件項目不會讓你自然而然地成為一個更好的程序員。編程馬拉松甚至可能會成為負面影響,如果它們讓你覺得構建軟件有任意期限,同時疲憊是生產出任何有價值的東西的一種合理途徑的話。在你富有成效的工作時間中有很多固有的限制。如果你不喜歡回家以後再花費時間去編碼,那就不要過於疲憊,做事也不要拖三拖四和三心二意。

在業餘項目上花費時間確實有一定的價值,但是最有用的結果不僅僅是實踐更是掌握了更多的知識。建立軟件項目往往使用較老的技術和工藝,因為這些工藝技術已經存在了一段時間。你從工作的其他軟件項目和與工作之外的開發人員交流中得到的有價值的知識是:

更廣泛的技術和工具。

新的技術和進程。也許你的公司沒有做太多的測試,但你可以在其他地方了解測試驅動開發。

擁有廣泛的工具和技術無論是對於你現在的工作還是想找一份新工作,都是一個寶貴的技能。但實際的編碼並不是獲得這方面知識的有效方法。因為其實你並不需要使用新的工具和技術,並且無論怎麼樣你永遠不會真正有時間去詳細學習所有的工具和所有的技術。你只能通過了解現在流行什麼工具和技術,這些工具和技術能做什麼,以及什麼情況下能發揮它們最大作用來獲取最有價值的內容。如果你發現了一個能立即應用到工作中的新工具,那麼你可以在工作中學習這個新工具,如果不能應用到工作中,那麼你只能在大腦中歸類等以後來使用它。

學習新的工具也可以幫助你找到新的工作,甚至實際上你沒有使用過它們。我曾在一次面試中被問到關於NoSQL和傳統數據庫的區別。老實說,那時的我從來沒有使用過MongoDB或其他任何NoSQL數據庫,但因為我曾了解過,所以我知道怎麼圓滿地回答。能夠回答這個問題使得面試官相信我能在必要時使用該工具,即使以前我沒有使用過。

與在業餘時間編碼相比,通過直接專註於獲取新的工具和技術方面的知識,也可以獲得相同的好處,並且更有效率。而且,由於這方面的知識將有利於你的僱主,所以你不需要在上面花費顯著的時間,就可以在工作時間內獲取這方面的知識。你覺得每一天都沒有真正空閑的時間,但你總有一段時間是無所事事耗費在互聯網上的。也許你現在正在網上衝浪!你可以利用這段時間來擴大你的知識面。

每周你都應該安排一個小時的時間去學習新的工具和技術。選擇一個特定的時間可以幫助你養成一個習慣。就我個人而言,我會選擇在周五下午,因為在這個時間段我反正也沒什麼可做的。不要因為項目期限的逼近或感到疲勞而跳過這個學習時間。你會在截止時間內做的更好,也不會那麼累,如果你知道正確的工具和技術來高效解決工作中遇到的問題的話。

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9439

沐鳴註冊網站_JavaScript中this指向問題

記得初學 JavaScript 時,其中 this 的指向問題曾讓我頭疼不已,我還曾私自將其與閉包、原型(原型鏈)並稱 js 武林中的三大魔頭。如果你要想在 js 武林中稱霸一方,必須將這三大魔頭擊倒。個人認為在這三大魔頭中,this 指向問題的武功最菜(難度最低)。俗話說柿子撿軟的捏,那我們就先從 this 指向問題下手。

先記住攻克 this 指向問題的口訣(前輩們的總結):哪個對象調用函數,函數里的 this 就默認指向哪個對象(注意 this 只能指向對象)。這裏說“默認指向”是因為我們通過箭頭函數、call、apply、bind等手段來改變 this 的指向。現在我們只討論 this 的默認指向。

全局作用域下以及全局作用域的函數中,this默認指向全局對象window

在嚴格模式下,全局作用域的函數中,this默認指向 undefined, 這是嚴格模式所規定的。

// 非嚴格模式下
console.log(this); // Window
function doSomething(){
    console.log(this); // Window
}
doSomething(); // 這裏可以看成window.doSomething(),所以函數里的this指向全局對象window
// 嚴格模式下
'use strict';
console.log(this); // Window
function doInStrict(){
    console.log(this); // undefined
}
doInStrict();

對象里的函數,this指向該對象

var a = 1;
var obj = {
    a: 2,
    fn: function(){
        console.log(this); // {a: 2, fn: ƒ}
        console.log(this.a); // 2
    }
};
obj.fn();

上面函數被調用后,從打印結果可以看出此時 this 指向的是調用函數的對象 obj。如果將對象中的函數賦給全局對象中定義的變量 fn1,執行 fn1 又會出現什麼結果呢?

var a = 1;
var obj = {
    a: 2,
    fn: function(){
        console.log(this); // Winidow
        console.log(this.a); // 1
    }
};
var fn1 = obj.fn;
fn1(); // 可以看成window.fn1();

從上面的例子可以看出,fn1 與 obj.fn 指向的函數是相同的,但是調用它的對象不同,那麼函數中 this 的指向也就不一樣了。

再看一個比較複雜的例子:

var a = 0;
function fn(){
	consoloe.log(this.a);
}
var obj1 = {
	a: 1,
	fn: function(){
		console.log(this.a);
	}
};
var obj2 = {
	a: 2,
	fn: function(){
		fn();
		obj1.fn();
		console.log(this.a);
	}
}
obj2.fn();

先說下執行結果,分別打印 0 1 2。當 obj2 調用 fn 函數時,先執行的是 fn(),這個函數是在全局作用域中定義的,該調用可以看成 window.fn(),所以,該函數內部的 this 指向的是 window 全局對象,this.a 自然就是全局對象中的 a 值(0)。

接着執行的是 obj1.fn(),它會從 obj1 中找到 fn 函數並執行。obj1 中的函數 fn 執行時調用它的對象是 obj1,所以,此時函數內部的 this 指向的就是 obj1 自身。那麼 this.a 查到的值也就是對象 obj1 中 a 的值(1)。

最後打印函數中 this 所處的函數 fn 是被 obj2 調用的,那麼自然而然 this 就指向了 obj2,所以 this.a 的結果就是 2 了。

從上面這個例子我們可以看出:函數內部 this 指向跟調用函數的對象有關,跟函數在哪裡調用沒有關係。

Window內置函數的回調函數中,this指向Window對象。

window 的內置函數( setInterval setTimeout 等),其回調函數中的 this 指向的是window對象。

var name = 'window';
var obj = {
    name: 'obj',
    func: function(){
        setTimeout(function () {
            console.log(this.name) // window
        },1000)
    }
}

obj.func()

但是一般在開發中,很多場景都需要改變 this 的指向。
this 既不指向函數自身也不指向函數的詞法作用域,this 實際上是在函數被調用時發生的綁定,它指向什麼完全取決於函數在哪裡被調用。
找到函數直接調用的位置後用下面的幾條規則就可以判斷出 this 的綁定對象。

  1. 由 new 調用?綁定到新創建的實例對象上。
  2. 由 call、apply、bind調用?綁定到指定的對象上。
  3. 由上下文對象調用?綁定到那個上下文對象上。
  4. 默認:在嚴格模式下綁定到 undefined,否則綁定到全局對象 Window 上。
  5. ES6 中的箭頭函數會繼承外層函數調用的 this 綁定,這和 var self = this;的綁定機制一樣。

來自:https://www.cnblogs.com/laozhenHome/p/13262592.html

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9430

沐鳴總代理_JavaScript重構技巧_ 數組,類名和條件

JavaScript 是一種易於學習的編程語言,編寫運行並執行某些操作的程序很容易。然而,要編寫一段乾淨的JavaScript 代碼是很困難的。

在本文中,我們學習如何使用數組來代替條件語句,以及如何使用classList操作類名。

用數組檢查替換長表達式

平時開發中,我們可能會寫如下的代碼:

if (fruit === 'apple' || fruit === 'orange' || fruit === 'grape') {
  //...
}

對於上面,我們可以使用一些數組方法來減少條件表達式的長度。

一種方法是使用數組的include方法:

if (['apple', 'orange' ,'grape'].includes(fruit)) {
  //...
}

如果傳遞給參數的值包含在數組實例中,include方法返回true,否則返回false。

另一種方法是使用數組的some方法:

if (['apple', 'orange', 'grape'].some(a => a === fruit)) {
  //...
}

通過some方法,我們可以檢查回調中是否存在具有給定條件的數組元素。

如果存在一個或多個,則返回true,否則返回false。

在 DOM 元素中使用 classList 屬性

檢查 DOM 元素中是否存在類並操作多個類的最簡單方法是使用classList屬性。

例如,如果要添加多個類,可以使用下面方式:

const p = document.querySelector('p');
p.classList.add('foo');
p.classList.add('bar');
p.classList.add('baz');

這樣,我們可以添加多個類而無需操作字符串。 我們只是獲得DOM元素對象的classList屬性,然後調用add通過將帶有類名的字符串傳遞到add方法中來添加類。

現在,渲染的DOM元素具有foo,bar和baz類。

同樣,我們可以調用classList屬性的remove方法,該方法使用一個帶有要刪除的類名的字符串來刪除該類。

例如,我們可以這樣寫:

const p = document.querySelector('p');
p.classList.add('foo');
p.classList.add('bar');
p.classList.add('baz');
p.classList.remove('baz');

要檢查 DOM 元素對象中是否存在類名,可以使用contains方法。

例如,我們可以這樣寫:

const p = document.querySelector('p');
p.classList.add('foo');
p.classList.add('bar');
const hasBaz = p.classList.contains('baz');

上面判斷 p 元素是否包含 baz 類,因為 p 沒有包含 baz類,所以返回 false。

classList屬性還有toggle方法,表示切換類(添加或者移除),例如下面的代碼:

const p = document.querySelector('p');
const button = document.querySelector('button');
p.classList.add('foo');
p.classList.add('bar');

button.onclick = () => {
  p.classList.toggle('bar');
}

每點擊一次按鈕,p 的上 bar 類就會添加或者移除。

clasList屬性有一個類似數組的可迭代對象,稱為DOMTokenList對象。因此,我們可以使用展開操作符將其轉換為數組,將clasList轉換為一個帶有類名的字符串數組。

例如,我們可以這樣寫:

const p = document.querySelector('p');
p.classList.add('foo');
p.classList.add('bar');
const classArr = [...p.classList];

上面 classArr 最終值為[“foo”, “bar”]。

一旦我們將DOMTokenList轉換為一個數組,那麼我們就可以使用任何數組方法來操作代碼。

總結

帶有 || 操作的長條件語句,我們使用對應數組方法來進行優化。

要操作多個類名,我們應該使用作為DOM元素對象一部分的classList屬性。通過這種方式,我們可以添加、刪除和切換類,而不需要操作字符串並自己將其設置為className屬性。

原文:https://levelup.gitconnected.com/javascript-refactoring-tips-making-functions-clearer-and-cleaner-c568c299cbb2

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9292

沐鳴怎麼當代理?_深入探索 CSS Grid

簡介

本教程將深入探討 css 網格布局,並探索幾乎所有的屬性和功能。讀完之後,你將能夠用這種出色的 css 附加功能去處理任何一種布局。

術語:Grid

Grid 是二維網格系統。它可以用來構建複雜的布局以及較小的界面。

屬性:display

只需要把一個元素的 display 屬性設置為 grid,它就成了網格。

.grid-to-be {
    display: grid;
}

這樣就使 .grid-to-be 成為 grid 容器,並使其子項成為 grid 項目

術語:網格線

在定義明確的網格軌道時會創建網格線。你可以用它們去放置網格項

術語:網格軌道

網格線是兩條網格線之間的空間。網格中的行和列是網格軌道。

屬性:grid-template-columns

可以使用 grid-template-columns 屬性來創建列。要定義列,應該按照你希望它們在網格中出現的順序,把grid -template-columns 屬性設置為列大小。我們來看一下:

.grid {
    display: grid;
    grid-template-columns: 100px 100px 100px;
}

這裏定義了三個寬度為 100px 的列。所有網格項將會按順序排列在這些列中。行高將等於該行中最高元素的高度,但是可以用 grid-template-rows 來進行更改。

請注意,在僅定義列而未定義行的情況下,元素將會填充列,然後在行中折返。這是由於 Grid 使用了網格線和網格線創建的隱式網格。

屬性:grid-template-rows

grid-template-rows 用於定義網格中行的數量和大小。它的語法和 grid-template-columns 類似。

.grid {
    display: grid;
    grid-template-columns: 100px 100px 100px;
    grid-template-rows: 100px 100px 100px;
}

如果只有 grid-template-rows 而沒有 grid-template-columns 屬性會導致列寬等於該行中最寬元素的寬度。

屬性:grid-template

grid 是 grid-template-rowsgrid-template-columns 和 grid-template-areas 三個屬性的簡寫。

使用方式如下:

.grid {
    grid-template:
        "header    header     header"  80px
        "nav       article    article" 600px
        / 100px 1fr;
}

你可以像平時那樣去定義模板區域,將每行的寬度放在最右面,最後再把所有列的寬度放在正斜杠之後。像以前一樣,你可以把所有內容放在一行。

數據類型:

fr 是為 css 網格布局創建的新單位。 fr 使你不需要計算百分比就能創建靈活的網格, 1fr 表示可用空間的一等份。可用空間被分為等份数字的總數個,所以 3fr 4fr 3fr 把空間劃分為 3 + 4 + 3 = 10 個部分,分別為三行或列分配 3、4 和 3 個等份的可用空間。例如:

.grid {
    display: grid;
    grid-template-columns: 3fr 4fr 3fr;
}

如果將固定單位與彈性單位相混合,則每個等份的可用空間是在減去固定空間後計算的。讓我們看另一個例子:

.grid {
    display: grid;
    grid-template-columns: 3fr 200px 3fr;
}

單個等份的寬度是這樣計算的:( .grid 的寬度 – 200px) / (3 + 3) 。如果存在間隔(gutter)的話,其空間一開始也會從 .grid 的寬度中減去。這是 fr 和 % 之間的區別,即百分比不包括你用 grid-gap 定義的 gutter。

這裏的 3fr 200px 3fr 基本上等於 1fr 200px 1fr。

顯式網格和隱式網格

顯式網格是使用屬性 grid-template-rows 或 grid-template-columns 創建的網格。隱式網格由 Grid 創建的 網格線 和 網格軌道 組成,用來保存帶有 grid-template-* 屬性的手動創建的網格之外的項目。

自動放置(Auto-placement)

當我們創建這樣的網格時:

.grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
}

即使我們只定義了列,但作為 .grid 直接子項的單個單元格仍按行放置。這是因為 Grid 包含自動放置規則。

屬性:grid-auto-columns

沒有被 grid-template-columns 所定義的隱式創建的網格列軌道所創建的列的大小,可以用 grid-template-columns 屬性定義,其默認值為 auto;你可以把它設置為自己所需要的值。

.grid {
    display: grid;
    grid-template-columns: 100px 100px 100px;
    grid-auto-columns: 50px;
}

屬性:grid-auto-rows

grid-auto-rows 的工作方式類似於 gridtemplatecolumns 。

.grid {
    display: grid;
    grid-template-rows: 100px 100px 100px;
    grid-auto-rows: 50px;
}

屬性:grid-auto-flow

grid-auto-flow 屬性控制 網格單元 如何流入網格,其默認值為 row

.grid {
    display: grid;
    grid-template-columns: 100px 100px 100px;
    grid-auto-flow: column;
}

上面網格中的“網格單元”將會被一一填充,直到沒有剩餘的項目為止。

基於行的放置

用行號將項目放置在網格中的操作被稱為基於行的放置。

屬性:grid-row-start

如果你希望特定的網格項從特定的行開始,則可以這樣:

.grid-item {
    grid-row-start: 3;
}

屬性:grid-row-end

如果你希望特定的網格項目在特定的行上結束,則可以這樣:

.grid-item {
    grid-row-end: 6;
}

屬性:grid-column-start

如果你希望特定的網格項目從特定的列開始,可以這樣:

.grid-item {
    grid-column-start: 3;
}

屬性:grid-column-end

如果你希望特定的網格項在特定的列上結束,可以這樣:

.grid-item {
    grid-column-end: 6;
}

屬性:grid-row 和 grid-column

可以用 grid-row 和 grid-column 屬性來手動放置和調整網格項目的大小。每個屬性都是其各自的 star 和 end 屬性的簡寫:grid-row-startgrid-row-endgrid-column-start 和 grid-column-end

用正斜杠 “/ ”來分隔開始和結束值:

.grid-item {
    grid-column: 3 / 5;
    grid-row: 2 / 7;
}

屬性:grid-area

你可以把 grid-area 用於對網格行和網格列的簡寫。它是這樣的:/ / /

.grid-item {
    grid-area: 2 / 3 / 7 / 5;
}

該代碼的行為與上一個標題中的代碼相同。

跨網格的元素

要使一個元素跨網格,可以使用 grid-row 或 grid-column 屬性。設置起始行 1 和結束行 -1。此處 1 表示相關軸上最左邊的網格線,-1 表示相關軸上最右邊的網格線。在從右到左的書寫腳本中,這是相反的,即 1 表示最右邊的行,-1 表示最左邊的行。

.grid-item-weird {
    grid-column: 1 / -1;
}

如果你希望單個項目佔據整個網格,可以對 grid-row 和 grid-column 都這樣做:

.grid-item-weird {
    grid-row: 1 / -1;
    grid-column: 1 / -1;
}

或者簡單地:

.grid-item-weird {
    grid-area: 1 / 1 / -1 / -1;
}

關鍵字:span

當使用 grid-row 和 grid-column 時,不用顯式定義行號,而是可以用 span 關鍵字來聲明該項應涵蓋的行數或列數:

.grid-item {
    grid-column: 3 / span 2;
}

你也可以把項目固定在終點線上,並朝另一個方向跨越。下面的代碼實現了與上面相同的結果:

.grid-item {
    grid-column: span 2 / 5;
}

可以用相同的方式把 span 應用在行上。

術語:網格單元

網格單元格是四個相交的網格線之間的空間,就像表格中的單元格一樣。

術語:網格區域

網格區域是佔據網格上一個矩形區域的網格單元。它們是用命名的網格區域或基於行的放置創建的。

屬性:grid-template-areas (& grid-area)

除了用諸如 span、grid-column之類的東西放置和調整單個網格項目外,還可以用所謂的“模板區域”。grid-template-area 允許你命名網格區域,以便網格項目可以進一步填充它們。

.grid {
    display: grid;
    grid-template-columns: 100px 1fr 100px;
    grid-template-rows: 100px 800px 100px;
    grid-template-areas:
        "header     header   header"
        "sidebar-1  content  sidebar-2"
        "footer     footer   footer"
}

這裏的一對引號代表一行網格。你可以將所有內容放在一行中,而不用列對齊,但是我所做的只是為了使它看起來更加整潔。我首先定義了三列三行,然後為每個單元命名。通過在第一行中重複執行三次 “header”,告訴 css 要做的是用名為 header 的網格項覆蓋整個過程。其餘的也一樣。

以下是通過用 grid-template-areas 命名每個網格項目,使其擁有為其定義的空間的方式:

.header {
    grid-area: header
}

.sidebar-1 {
    grid-area: sidebar-1
}

.content {
    grid-area: content
}

.sidebar-2 {
    grid-area: sidebar-2
}

.footer {
    grid-area: footer
}

沒有什麼比這更容易了,尤其是用於布置內容的 css 其他方法。

在前面你已經看到 grid-area 也用於基於行的定位。

如果想把單元格留空,則可以用點 . 來設置:

.grid {
    display: grid;
    grid-template-columns: 100px 1fr 100px;
    grid-template-rows: 100px 800px 100px;
    grid-template-areas:
        "header header header"
        "sidebar content sidebar"
        "footer footer ."
}

在這裏,頁腳以第二列結束。

屬性:grid-template

grid 是 grid-template-rowsgrid-template-columns 和grid-template-areas 三個屬性的簡寫。

使用方式如下所示:

.grid {
    grid-template:
        "header    header     header"  80px
        "nav       article    article" 200px
        / 100px auto;
}

可以像通常那樣定義模板區域,把每行的寬度放在其最右面,然後將所有列的寬度放在正斜杠之後。像以前一樣,你可以把所有得內容放在同一行。

函數:repeat()

repeat() 函數有助於使 網格軌道 列表變得不是那麼多餘,併為其添加了語義層。使用起來非常簡單直觀。我們來看一下:

你也可以重複某種形式的軌道列表,如下所示:

.grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr 2fr); // this is the same as: 1fr 2fr 1fr 2fr 1fr 2fr
}

repeat() 不必是值的唯一部分。你可以在其前後添加其他的值。例如:grid-template-columns:2fr repeat(5,1fr) 4fr;。

屬性:grid

這裏的 grid 是 grid-template-rows、 grid-template-columns、 grid-template-areas、 grid-auto-rows、 grid-auto-columns 和 grid-auto-flow 六個屬性的簡寫。

首先,你可以像這樣使用 grid-template(上一個示例):

.grid {
    grid:
        "header    header     header"     80px
        "nav       article    article"    200px
        / 100px auto;
}

其次它不是你看上去的那樣,grid 與 css 屬性不一樣:

是的,你沒有看錯:一個名為 css 的屬性,所有 css 屬性的簡寫。我也是在某次思考中偶然知道了它。但是現在我不會教你怎麼用,以後有可能會。

第三,你以某種方式使用 grid。你可以將 grid-template-rows 與 grid-auto-columns 或 grid-auto-rows 結合使用。語法非常簡單:

.grid-item {
    grid: <grid-template-rows> / <grid-auto-columns>; 
    grid: <grid-auto-rows> / <grid-template-columns>; 
}

例如:

.grid-item-1 {
    grid: 50px 200px 200px/ auto-flow 60px;
}

.grid-item-2 {
    grid: auto-flow 50px / repeat(5, 1fr);
}

請注意,在該值之前應該先使用 auto-flow 關鍵字。

術語:Gutter

Gutter 是單獨分隔 網格行 和 網格列 的空間。 grid-column-gapgrid-row-gap 和 grid-gap 是用於定義 gutter 的屬性。

屬性:grid-row-gap

grid-row-gap 用於定義各個 網格行 之間的空間。它是這樣的:

.grid {
    display: grid;
    grid-template-rows: 100px 100px 100px;
    grid-row-gap: 10px;
}

這會將 網格行 彼此隔開10個像素。

屬性:grid-column-gap

grid-column-gap 用於定義各個 網格列 之間的空間。它是這樣的:

.grid {
    display: grid;
    grid-template-columns: 100px 100px 100px;
    grid-column-gap: 10px;
}

這會將 網格列 彼此隔開 10 個像素。

屬性:grid-gap

grid-gap 是將 grid-column-gap 和 grid-row-gap 結合在一起的簡寫屬性。一個值定義了兩個 gutter。例如:

.grid {
    display: grid;
    grid-template-columns: 100px 100px 100px;
    grid-template-rows: 100px 100px 100px;
    grid-gap: 10px;
}

屬性:order

可以用 order 屬性來控制網格單元的順序。看下面的例子:

.grid {
    display: grid;
    grid-template-columns: 100px 100px 100px;
    grid-template-rows: 100px 100px 100px;
    grid-gap: 10px;
}

.grid .grid-cell:nth-child(5) {
    order: 1;
}

在代碼中,第五個網格單元被放置在網格的最後,因為其他網格單元根本沒有定義順序。如果定義了順序,則會遵循数字順序。兩個或多個 網格單元 可以有相同的順序。具有相同順序或完全沒有順序的文件將會根據 html 文檔的邏輯順序進行放置。再看下面:

.grid {
    display: grid;
    grid-template-columns: 100px 100px 100px;
    grid-template-rows: 100px 100px 100px;
    grid-gap: 10px;
}

.grid .grid-cell {
    order: 1
}

.grid .grid-cell:nth-child(5) {
    order: 2;
}

上面的例子產生的結果與前面的例子相同。

函數:minmax()

maxmax() 函數是 css 網格布局的新增功能。此功能為我們提供了指定 網格軌道 的最小和最大尺寸的方法。

看下面的例子:

.grid {
    display: grid;
    grid-template-columns: 1fr minmax(50px, 100px) 1fr;
}

使用上面的代碼,在減小窗口寬度時,中間列將保持 100px 的寬度,直到第一列和最後一列減小到其內容的寬度為止。這對於製作響應式布局特別有用。

關鍵字:auto

如果父容器的尺寸是固定的(例如固定寬度),則 auto 關鍵字作為網格項目的寬度將會使該項目充滿容器的整個寬度。在有多個項目的情況下,就像 fr 那樣劃分空間。但是如果將 auto 與 fr 一起使用,則 auto 表現為該項目內容的寬度,剩餘的可用空間被劃分為 fr。

函數:fitcontent()

當你希望寬度或高度表現得像 auto 一樣,但又希望受到最大寬度或高度約束時,可以用 fitcontent() 函數.

.grid-item {
    width: fitcontent(200px);
}

在這裏,最小為適合內容,最大為 200px。

關鍵字:auto-fill

你可以用 auto-fill 來用最多的 網格軌道 填充相關的軸(行或列)而不會溢出。要實現這個目的,需要用到 repeat() 函數:

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, 50px);
}

但這會降低單個軌道的靈活性。通過與 minmax() 一起使用,可以同時具有自動填充功能和靈活性。

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));
}

這樣,你可以至少包含一列,並且在特定瀏覽器寬度中包含多個 50px 的列。

請注意,即使可能未用單元格填充,
auto-fill 也會創建網格軌道。

auto-fit

auto-fit 的行為與 auto-fill 相同,不同之處在於它會摺疊所有空的重複軌道。空軌道是指沒有放置網格項目或跨越網格項目的軌道。

dense

藉助 dense 關鍵字,你可以將項目回填到 空網格單元 中,這些單元是因為你嘗試做了一些的奇怪的事(例如spanning)而被創建的。在任何 span 內你都可以將 dense 關鍵字與 grid-auto-flow 配合使用,如下所示:

.grid {
    display: grid;
    grid-template-column: repeat(auto-fill, minmax(50px, 1fr));
    grid-auto-flow: dense;
}

你可以把它用在照片庫之類的頁面中,但在用於表單時要特別小心,因為這可能會打亂表單子元素的特定順序。

瀏覽器支持

在撰寫本文時,瀏覽器對 css 網格布局有很好的支持。根據 caniuse.com 的說法,除了 Internet Explorer 11部分支持 -ms 前綴和 Opera Mini 之外,所有主流瀏覽器均支持 CSS 網格布局。

總結

與以前的方法相比,CSS 網格使我們能夠以更高的控制力、便捷性和速度來進行布局。在本教程中,我們學習了 Grid 的所有主要元素,包括創建軌道、定位和調整單元格的大小,以及使網格流暢和響應,以及使用諸如 auto-fill 和 minmax() 之類的關鍵字。

本文首發微信公眾號:前端先鋒

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9123

沐鳴註冊網站_轉行web前端,需要哪些工具和需要學習什麼?

今天我們來談談Web和前端開發過程中需要學習什麼?前端開發需要使用什麼開發工具?也簡單介紹前端開發前景和薪水。

前端工程師的主要職責:

前端工程師在不同的公司有不同的功能,但性質相似。

1、網站設計與網頁界面開發

2、做網站界面開發

3、Web界面開發,前端數據綁定,前台邏輯

4、設計、開發、數據

web前端開發中需要掌握的技術:

1、學習html,這是最簡單,最基本的是要掌握div,formtable、Ulli、P、跨度、字體這些標籤,這些都是最前端的學習都是需要不斷的學習,學一天停一停相當於白學。

2、學習css,css這裏說的不包括css3 Web前端開發工程師裏面我們看到的,一個可以使用html或css + css+div的界面布局,所以css是用來協助html布局和显示,我們稱之為“css樣式”,為什麼說div+css?因為我說div是html主要用於布局的,所以div是這個東西的核心!css必須配合部。css必須掌握浮、位置、寬度和高度,以及最大值和最小值,以100%,溢出,邊緣、填充等。這些都是與布局相關的樣式。

3、js。你覺得還過的去,看看js是可怕的,事實上,js入門很簡單,不需要很多東西,只要根據ID或名稱DOM或”風格,或價值,然後以一個ID或名稱元標籤,或額外的數據,在html,這是對數據的操作有關係,那麼數據邏輯的影響,無非是一個跳躍,彈框,隱藏什麼,這一切都是結合其他應用,代碼一點都不難,將這些基本的js。百度其他好。然後多看一些,不是什麼問題。

4、學習jQuery,相當於封裝一組js插件的js。其目的是操作更方便,編寫更少的代碼,jQuery條目也非常簡單。這些都是切入點,要學會像js,只是改變了JQ代碼。剩下的就跟百度一樣。

5、最好是指出背景語言,如java,php,為什麼?因為我們是前台接口數據,從後台到點,如果後台代碼,你知道如何與後台數據交互是最好的,它節省了時間,也可以使前端代碼更加規範。否則,可能是因為你回來了,無法忍受的數據,然後前端代碼再次重寫,這將是可怕的。

6、研究CSS3 + html5

以上6點,基本上是一個web前端開發工程師掌握的技術,我也試着講述一下自己的經驗,但是我們不認為上面的6點只是我說的那麼簡單,沒有,他們正在使用,這是在這樣的一個火中,因為堅強!我說的就是這麼簡單,你覺得原因很難祛除,萬事開頭難,我說的是方法和技巧的入門,需要了解的東西。除了告訴你一個秘密,不要以為代碼很難敲,現在什麼語言都有自動提示代碼功能,只需要輸入一個字符,兩個字符,後面的代碼就會彈出,讓你選擇!你害怕什麼?所以不要害怕你糟糕的英語。

web前端開發中需要用到的工具:

有一個ediplus,這是這是一個字體顏色的記事本等,我用這個,因為我覺得DW佔用太多的內存,使電腦卡,所以我用寫ediplus代碼,代碼有沒有自動提示,我不知道,你可以百度是否有插件。Eclipse可以寫java,php和上面的各種代碼!zendstudio是專寫php,但上述2個工具是比較專業的,這是由我們的專業開發人員使用,所以你可以看到,PS圖像處理軟件是沒有必要的。

web前端開發展望:

web前端開發的前景是非常好的。我們不在乎我們做什麼網站或者我們在做什麼項目。現在我們都在關注用戶體驗。人們說,如果你的網站界面看起來不錯,你的網站和項目將成功3/4。所以現在很多人說Web前端的開發前景略好於後端開發。但我做一個比較,前端開發技術的學習上,後端開發技術開發技術還了解到,前、後端開發薪酬肯定是遠遠高於前面,但後面的開發技術在一定程度上會有一個很大的瓶頸,因此早期的中級程序員,前端開發後端開發更好,那麼高級程序員。

前端開發工資薪酬:

這是一個敏感的話題,在上海,0~1年Web前端開發工作經驗的工資是8k ~ 12K,工資取決於你的情況.我們從事這個行業的技術,你的技術有多少薪水,在這條線上的技術無法相比,因為主要還是取決於你的個人技術能力。

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9311

沐鳴娛樂怎麼樣?_原生JS利用transform實現banner的無限滾動

功能

  • 默認情況無限循環向右移動
  • 點擊数字切換到對應圖片
  • 點擊左右切換可切換圖片

原理

首先說下原理。

  1. 在布局上所有的圖片都是重疊的,即只要保證Y方向對齊即可,當前可見的圖z-index層級最高。
  2. 每隔3s中更換一張圖片,使用setTimeout定時。
  3. 使用gIndex記錄當前可視區域的展示的是哪張圖片下標,每次更換,計算下一張圖片的下標。
  4. 通過requestAnimationFrame實現一次圖片切換的動畫。

這種方法也可以做到整個頁面始終只有2個img標籤,而不必把所有的img節點全部創建出來,要點是每次更換不可見img的src。

動畫的實現

  1. 首先定義一個timestap,這個值記錄每個幀移動多少距離。定義初始step=0,記錄移動的步數。
  2. 每次移動的距離moveWidth是timestamp*step,圖片1向右移動增加moveWidth,圖片2從左側進入moveWidth。因此,圖片1的transform是translate(moveWidth), 而圖片2的transform則是translate(moveWidth-圖片寬度)。
  3. step+1
  4. 如果moveWidth>圖片寬度,步驟5,否則requestAnimationFrame請求下一次執行,繼續2-4.
  5. 圖片1和2都將位置放置在起始位置,圖片2的z-index設置為最高。

這樣就完成了一次移動的動畫。

html代碼

<header>
    <div class="box">
        <img src="imgs/banner1.jpg">
        <img src="imgs/banner2.jpg">
        <img src="imgs/banner3.jpg">
        <img src="imgs/banner4.jpg">
    </div>
    <div class="buttons">
        <div class="active">1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
    </div>
    <div class="left">
        <div class="arrow"></div>
    </div>
    <div class="right">
        <div class="arrow"></div>
    </div>
</header>

js代碼

var timeout = null;
window.onload = function () {
    var oLeft = document.querySelector('.left');
    var oRight = document.querySelector('.right');
    var oButton = document.querySelector('.buttons');
    var oButtons = document.querySelectorAll('.buttons div');
    var oImgs = document.querySelectorAll('.box img');
    var imgWidth = oImgs[0].width;
    var gIndex = 0;
    begainAnimate();

    // 綁定左右點擊事件
    oLeft.onclick = function () {
        clearTimeout(timeout);
        leftMove();
        begainAnimate();
    };
    oRight.onclick = function () {
        clearTimeout(timeout);
        rightMove();
        begainAnimate();
    };
    // 綁定数字序號事件
    oButton.onclick = function (event) {
        clearTimeout(timeout);
        var targetEl = event.target;
        var nextIndex = (+targetEl.innerText) - 1;
        console.log(nextIndex);
        rightMove(nextIndex);
        begainAnimate();
    }
    // 默認初始動畫朝右邊
    function begainAnimate() {
        clearTimeout(timeout);
        timeout = setTimeout(function () {
            rightMove();
            begainAnimate();
        }, 3000);
    }
    // 向左移動動畫
    function leftMove() {
        var nextIndex = (gIndex - 1 < 0) ? oImgs.length - 1 : gIndex - 1;
        animateSteps(nextIndex, -50);
    }
    // 向右移動動畫
    function rightMove(nextIndex) {
        if (nextIndex == undefined) {
            nextIndex = (gIndex + 1 >= oImgs.length) ? 0 : gIndex + 1;
        }
        animateSteps(nextIndex, 50);
    }
    // 一次動畫
    function animateSteps(nextIndex, timestamp) {
        var currentImg = oImgs[gIndex];
        var nextImg = oImgs[nextIndex];
        nextImg.style.zIndex = 10;
        var step = 0;
        requestAnimationFrame(goStep);
        // 走一幀的動畫,移動timestamp
        function goStep() {
            var moveWidth = timestamp * step++;
            if (Math.abs(moveWidth) < imgWidth) {
                currentImg.style.transform = `translate(${moveWidth}px)`;
                nextImg.style.transform = `translate(${moveWidth > 0 ? (moveWidth - imgWidth) : (imgWidth + moveWidth)}px)`;
                requestAnimationFrame(goStep);
            } else {
                currentImg.style.zIndex = 1;
                currentImg.style.transform = `translate(0px)`;
                nextImg.style.transform = `translate(0px)`;
                oButtons[gIndex].setAttribute('class', '');
                oButtons[nextIndex].setAttribute('class', 'active');
                gIndex = nextIndex;
            }
        }
    }
}
window.onclose = function () {
    clearTimeout(timeout);
}

css布局樣式


<style>
    /* 首先設置圖片box的區域,將圖片重疊在一起  */
    header {
        width: 100%;
        position: relative;
        overflow: hidden;
    }
    .box {
        width: 100%;
        height: 300px;
    }
    .box img {
        width: 100%;
        height: 100%;
        position: absolute;
        transform: translateX(0);
        z-index: 1;
    }
    .box img:first-child {
        z-index: 10;
    }
    
    /* 数字序列按鈕 */
    .buttons {
        position: absolute;
        right: 10%;
        bottom: 5%;
        display: flex;
        z-index: 100;
    }

    .buttons div {
        width: 30px;
        height: 30px;
        background-color: #aaa;
        border: 1px solid #aaa;
        text-align: center;
        margin: 10px;
        cursor: pointer;
        opacity: .7;
        border-radius: 15px;
        line-height: 30px;
    }

    .buttons div.active {
        background-color: white;
    }

    /* 左右切換按鈕 */
    .left,
    .right {
        position: absolute;
        width: 80px;
        height: 80px;
        background-color: #ccc;
        z-index: 100;
        top: 110px;
        border-radius: 40px;
        opacity: .5;
        cursor: pointer;
    }

    .left {
        left: 2%;
    }

    .right {
        right: 2%;
    }

    .left .arrow {
        width: 30px;
        height: 30px;
        border-left: solid 5px #666;
        border-top: solid 5px #666;
        transform: translate(-5px, 25px) rotate(-45deg) translate(25px, 25px);
    }

    .right .arrow {
        width: 30px;
        height: 30px;
        border-left: solid 5px #666;
        border-top: solid 5px #666;
        transform: translate(50px, 25px) rotate(135deg) translate(25px, 25px);
    }
</style>

來自:https://segmentfault.com/a/1190000022929832

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9307

沐鳴登錄_有了 Promise 和 then,為什麼還要使用 async?

最近代碼寫着寫着,我突然意識到一個問題——我們既然已經有了 Promise 和 then,為啥還需要 async 和 await?這不是脫褲子放屁嗎?

比如說我們需要一段請求服務器的代碼:

new Promise((resolve, reject) => {
  setTimeout(() => {
    const res = '明月幾時有'
    if (1 > 2) {
      resolve(res)
    } else {
      reject('我不知道,把酒問青天吧')
    }
  }, 1500)
}).then(
  (res) => {
    console.log(`成功啦!結果是${res}`)
  },
  (err) => {
    console.log(`失敗了。。。錯誤是${err}`)
  }
)

這段代碼,簡潔漂亮,但是如果用上了 async 和 await,就需要寫成下面這樣:

function ask() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const res = '明月幾時有'
      if (1 > 2) {
        resolve(res)
      } else {
        reject('我不知道,把酒問青天吧')
      }
    }, 1500)
  })
}

async function test() {
  try {
    const res = await ask()
  } catch (err) {
    console.log(err)
  }
}

test()

竟然還需要一個 try catch 來捕捉錯誤!越寫越像 Java 呀。

MDN 給我們了一些解釋:

如果你在代碼中使用了異步函數,就會發現它的語法和結構會更像是標準的同步函數。

說白了,這種寫法的一部分原因,就是為了“討好” Java 和其他的一些程序員。

另一方面呢,也是增強可讀性,雖然說 async await 的寫法比較丑,但是毫無疑問,可讀性遠遠高於 Promise then。

最為重要的呢,是 Promise 可以無限嵌套,而 async await 只能處理一個 Promise,無法繼續嵌套。

所以一旦需要使用多次連續回調,async await 就乏力了。

其實也可以,通過 await 一個Promise.all()來實現。

作者:幾乎一米八的徐某某

出處:Aero Blog (https://www.cnblogs.com/xhyccc/)


站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9049

沐鳴平台_你真的懂遞歸嗎?

因為很多算法思想都基於遞歸,無論是DFS、樹的遍歷、分治算法、動態規劃等都是遞歸思想的應用。學會了用遞歸來解決問題的這種思維方式,再去學習其他的算法思想,無疑是事半功倍的。

遞歸的本質

無可奈何花落去,似曾相識燕歸來。

遞歸,去的過程叫“遞” ,回來的過程叫“歸”。

探究遞歸的本質要從計算機語言的本質說起。

計算機語言的本質是彙編語言,彙編語言的特點就是沒有循環嵌套。
我們平時使用高級語言來寫的 if..else.. 也好, for/while 也好,在實際的機器指令層面來看,就是一個簡單的地址跳轉,跳轉到特定的指令位置,類似於 goto 語句。

機器嘛,總是沒有溫度的。我們再來看一個生活中的例子,大家小的時候一定用新華字典查過字。如果要查的字的解釋中,也有不認識的字。那就要接着查第二個字,不幸第二個字的解釋中,也有不認識的字,就要接着查第三個字。直到有一個字的解釋我們完全可以看懂,那麼遞歸就到了盡頭。接下來我們開始後退,逐個清楚了之前查過的每一個字,最終,我們明白了我們要查的第一個字。

我們再從一段代碼中,體會一下遞歸。

const factorial = function(n) {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

factorial 是一個實現階乘的函數。我們以階乘 f(6) 來看下它的遞歸。

f(6) = n * f(5),所以 f(6) 需要拆解成 f(5) 子問題進行求解,以此類推 f(5) = n * f(4) ,也需要進一步拆分 … 直到 f(1),這是遞的過程。 f(1) 解決后,依次可以解決f(2)…. f(n)最後也被解決,這是歸的過程。

從上面兩個例子可以看出,遞歸無非就是把問題拆解成具有相同解決思路的子問題,直到最後被拆解的子問題不能夠拆分,這個過程是“遞”。當解決了最小粒度可求解的子問題后,在“歸”的過程中順其自然的解決了最開始的問題。

搞清楚了遞歸的本質,在利用遞歸思想解題之前,我們還要記住滿足遞歸的三個條件:

1.問題可以被分解成幾個子問題

2.問題和子問題的求解方法完全相同

3.遞歸終止條件

敲黑板,記筆記!


LeetCode 真題

我們拿一道 LeetCode 真題練練手。

求解斐波那契數列,該數列由 0 和 1 開始,後面的每一項数字都是前面兩項数字的和,也就是:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

給定 N,計算 F(N)。

遞歸樹如上圖所示,要計算 f(5),就要先計算子問題 f(4) 和 f(3),要計算 f(4),就要先計算齣子問題 f(3)和 f(2)…
以此類推,當最後計算到 f(0) 或者 f(1) 的時候,結果已知,然後層層返回結果。

經過如上分析可知,滿足遞歸的三個條件,開始擼代碼。

遞歸解法

const fib = function(n) {
    if (n == 0 || n == 1) {
        return n;
    }
    return fib(n - 1) + fib(n - 2);
}

或者可以這樣炫技:

const fib = n => n <= 0 ? 0 : n == 1 ? 1: fib(n - 2) + fib(n - 1);

還沒完事,記住要養成習慣,一定要對自己寫出的算法進行複雜度分析。這部分在專欄JavaScript算法時間、空間複雜度分析已經講解過,沒看過的同學請點擊鏈接移步。

複雜度分析

  • 空間複雜度為 O(n)
  • 時間複雜度 O(2^n)

總時間 = 子問題個數 * 解決一個子問題需要的時間

  • 子問題個數即遞歸樹中的節點總數 2^n
  • 解決一個子問題需要的時間,因為只有一個加法操作 fib(n-1) + fib(n-2) ,所以解決一個子問題的時間為 O(1)

二者相乘,得出算法的時間複雜度為 O(2^n),指數級別,裂開了呀。

面試的時候如果只寫這樣一種解法就 GG 了。

其實這道題我們可以利用動態規劃或是黃金分割比通項公式來求解,動態規劃想要講清楚的話篇幅較長,後續開個專欄會詳細介紹,這裏看不懂的同學們不要着急。

(選擇這道題的初衷是為了讓大家理解遞歸。)

動態規劃解法

遞歸是自頂向下(看上文遞歸樹),動態規劃是自底向上,將遞歸改成迭代。為了減少空間消耗,只存儲兩個值,這種解法是動態規劃的最優解。

  • 時間複雜度 O(n)
  • 空間複雜度 O(1)
const fib = function(n) {
    if (n == 0) {
        return 0;
    }
    let a1 = 0;
    let a2 = 1;
    for (let i = 1; i < n; i++) {
        [a1, a2] = [a2, a1 + a2];
    }
    return a2;
}

黃金分割比通項公式解法

  • 時間複雜度 O(logn)
  • 空間複雜度 O(1)
const fib = function(n) {
    return (Math.pow((1 + Math.sqrt(5))/2, n) - Math.pow((1 - Math.sqrt(5))/2, n)) / Math.sqrt(5);
}

除此之外,還可以利用矩陣方程來解題,這裏不再展開。

回到遞歸,在學習遞歸的過程中,最大的陷阱就是人肉遞歸。人腦是很難把整個“遞”“歸”過程毫無差錯的想清楚的。但是計算機恰好擅長做重複的事情,那我們便無須跳入細節,利用數學歸納法的思想,將其抽象成一個遞推公式。相信它可以完成這個任務,其他的交給計算機就好了。

如果你非要探究裏面的細節,挑戰人腦壓棧,那麼你只可能會陷入其中,甚至懷疑人生。南牆不好撞,該回頭就回頭。

你凝望深淵的時候,深淵也在凝望你。

原文:https://segmentfault.com/a/1190000022677431

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9061

沐鳴測速登錄地址_在JavaScript 中 14 個拷貝數組的技巧

數組拷貝經常被誤解,但這並不是因為拷貝過程本身,而是因為缺乏對 js 如何處理數組及其元素的理解。js 中的數組是可變的,這說明在創建數組之後還可以修改數組的內容。

這意味着要拷貝一個數組,咱們不能簡單地將舊數組分配給一個新變量,它也是一個數組。如果這樣做,它們將共享相同的引用,並且在更改一個變量之後,另一個變量也將受到更改的影響。這就是我們需要克隆這個數組的原因。

接着來看看一些關於拷貝何克隆數組的有趣方法和技巧。

技巧 1 – 使用Array.slice方法

const numbers = [1, 2, 3, 4, 5]

const copy = numbers.slice()
copy.push(6) // 添加新項以證明不會修改原始數組

console.log(copy)
console.log(numbers)

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 2 – 使用Array.map方法

const numbers = [1, 2, 3, 4, 5]

const copy = numbers.map( num => num )
copy.push(6) // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 3 – 使用Array.from 方法

const numbers = [1, 2, 3, 4, 5];

const copy = Array.from(new Set(numbers));
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 4 – 使用展開操作符

const numbers = [1, 2, 3, 4, 5];

const copy = [...numbers];
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出 
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 5 – 使用 Array.of 方法和展開操作符

const numbers = [1, 2, 3, 4, 5];

const copy = Array.of(...numbers);
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出 
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

Array.of() 方法創建一個具有可變數量參數的新數組實例,而不考慮參數的數量或類型。Array.of() 和 Array 構造函數之間的區別在於處理整數參數:Array.of(7) 創建一個具有單個元素 7 的數組,而 Array(7) 創建一個長度為7的空數組(注意:這是指一個有7個空位(empty)的數組,而不是由7個undefined組成的數組)。

Array.of(7);       // [7] 
Array.of(1, 2, 3); // [1, 2, 3]

Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]

技巧 6 – 使用 Array 構造函數和展開操作符

const numbers = [1, 2, 3, 4, 5];

const copy = new Array(...numbers);
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出 
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 7 – 使用解構

const numbers = [1, 2, 3, 4, 5];

const [...copy] = numbers;
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 8 – 使用 Array.concat 方法

const numbers = [1, 2, 3, 4, 5];

const copy = numbers.concat();
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 9 – 使用 Array.push 方法和展開操作符

const numbers = [1, 2, 3, 4, 5];

let copy = [];
copy.push(...numbers);
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 10 – 使用 Array.unshift 方法和展開操作符

const numbers = [1, 2, 3, 4, 5];

let copy = [];
copy.unshift(...numbers);
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 11 – 使用 Array.forEach 方法和展開操作符

const numbers = [1, 2, 3, 4, 5];

let copy = [];
numbers.forEach((value) => copy.push(value));
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 12 – 使用 for 循環

const numbers = [1, 2, 3, 4, 5];

let copy = [];
for (let i = 0; i < numbers.length; i++) {
    copy.push(numbers[i]);
}
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 13 – 使用 Array.reduce 方法

這個做法是可行,但比較多餘,少用

const numbers = [1, 2, 3, 4, 5];

const copy = numbers.reduce((acc, x) => { acc.push(x); return acc; }, []);
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

技巧 14 – 使用古老的 apply 方法

const numbers = [1, 2, 3, 4, 5];

let copy = [];
Array.prototype.push.apply(copy, numbers);
copy.push(6); // 添加新項以證明不會修改原始數組

console.log(copy);
console.log(numbers);

// 輸出
// [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5]

總結

請注意,上面這些方法執行的是淺拷貝,就是數組是元素是對象的時候,咱們更改對象的值,另一個也會跟着變,就能技巧4來說,如果咱們的數組元素是對象,如下所示:

const authors = [
  { name: '前端小智', age: 25 }, 
  { name: '王大冶', age: 30 }, 
]

const copy = [...authors ]
copy[0].name = '被更改過的前端小智'

console.log(copy)
console.log(authors)

所以上面的技巧適合簡單的數據結構,複雜的結構要使用深拷貝。數組拷貝經常被誤解,但這並不是因為拷貝過程本身,而是因為缺乏對 js 如何處理數組及其元素的理解。

原文:https://medium.com/

來源:twitter

譯者:前端小智  

站長推薦

1.雲服務推薦: 國內主流雲服務商,各類雲產品的最新活動,優惠券領取。地址:阿里雲騰訊雲華為雲

2.廣告聯盟: 整理了目前主流的廣告聯盟平台,如果你有流量,可以作為參考選擇適合你的平台點擊進入

鏈接: http://www.fly63.com/article/detial/9057