由 ianchen0419 發表的全部文章

Reference and Copy

By Value: Number, String, Boolean

Number

let age=100;
let age2=age;
console.log(age, age2); //100 100

age=200;
console.log(age, age2); //200 100

String

let name='wes';
let name2=name;
console.log(name, name2); //'wes' 'wes'

name='wesley';
console.log(name, name2); //'wesley' 'wes'

Boolean

let isGood=true;
let isGood2=isGood;
console.log(isGood, isGood2); //true true

isGood=false;
console.log(isGood, isGood2); //false true

By Reference: Object, Array, Function

const players = ['Wes', 'Sarah', 'Ryan', 'Poppy'];
const team = players;
console.log(players, team);
// ["Wes", "Sarah", "Ryan", "Poppy"]
// ["Wes", "Sarah", "Ryan", "Poppy"]

team[3]='Luis';
console.log(players, team);
// ["Wes", "Sarah", "Ryan", "Luis"]
// ["Wes", "Sarah", "Ryan", "Luis"]

//teams[3]的「team」是Reference,所以初始一但被更新,複製的也會被更新

Reference中的例外:該如何讓被複製的array不受初始變更的影響

方法1:slice

const fruits=['apple', 'banana', 'orange', 'grape'];
const fruits2=fruits.slice();

fruits[3]='mango';
console.log(fruits, fruits2);
// ["apple", "banana", "orange", "mango"]
// ["apple", "banana", "orange", "grape"]

方法2:New Array+contact

const fruits=['apple', 'banana', 'orange', 'grape'];
const fruits3=[].concat(fruits);

fruits[3]='mango';
console.log(fruits, fruits3);
// ["apple", "banana", "orange", "mango"]
// ["apple", "banana", "orange", "grape"]

方法3:ES6 Spread

const fruits=['apple', 'banana', 'orange', 'grape'];
const fruits4=[...fruits];

fruits[3]='mango';
console.log(fruits, fruits4);
// ["apple", "banana", "orange", "mango"]
// ["apple", "banana", "orange", "grape"]

方法4:Array.from

const fruits=['apple', 'banana', 'orange', 'grape'];
const fruits5=Array.from(fruits);

fruits[3]='mango';
console.log(fruits, fruits5);
// ["apple", "banana", "orange", "mango"]
// ["apple", "banana", "orange", "grape"]

多層物件中的淺拷貝

當1個物件他有很多層時

透過assign改第1層:不會改到初始物件

const wes={
 name: 'wes',
 age: 100,
 social: {
  twitter: '@webos',
  facebook: 'wesbos.developer'
 }
}

const dev=Object.assign({}, wes);
dev.name='wesley';
console.log(wes, dev);
// Object {
//   name: 'wes',
//   age: 100,
//   social: {
//    twitter: '@webos',
//    facebook: 'wesbos.developer'
//  }
// }
// Object {
//   name: 'wesley',
//   age: 100,
//   social: {
//    twitter: '@webos',
//    facebook: 'wesbos.developer'
//  }
// }

透過assign改第2層:會一起改到初始物件

const wes={
 name: 'wes',
 age: 100,
 social: {
  twitter: '@webos',
  facebook: 'wesbos.developer'
 }
}

const dev2=Object.assign({}, wes);
console.log(wes, dev);
// Object {
//   name: 'wesley',
//   age: 100,
//   social: {
//    twitter: '@coolman',
//    facebook: 'wesbos.developer'
//  }
// }
// Object {
//   name: 'wesley',
//   age: 100,
//   social: {
//    twitter: '@coolman',
//    facebook: 'wesbos.developer'
//  }
// }

原因:assign指能對第1層做深拷貝,其他第2層以下還是淺拷貝

多層物件的多重深拷貝(clone deep)

使用這招前請三思是否有必要多重深拷貝

const wes={
 name: 'wes',
 age: 100,
 social: {
  twitter: '@webos',
  facebook: 'wesbos.developer'
 }
}

const dev3=JSON.parse(JSON.stringify(wes));
dev3.social.twitter='@coolman';
console.log(wes, dev3);
// Object {
//   name: 'wesley',
//   age: 100,
//   social: {
//    twitter: '@wesbos',
//    facebook: 'wesbos.developer'
//  }
// }
// Object {
//   name: 'wesley',
//   age: 100,
//   social: {
//    twitter: '@coolman',
//    facebook: 'wesbos.developer'
//  }
// }

debounce

當執行某些event時(比如說scroll event),瀏覽器會執行很多次,這時可以用debounce function,限制他只能每xx毫秒執行一次,以節省效能

未使用debounce時

function goScroll(){
  console.count('gogogo');
}

window.addEventListener('scroll', goScroll);

//此時滑動螢幕捲軸,會發現後台被執行了很多次

使用debounce function減輕效能負擔

function debounce(func, wait = 20, immediate = true) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}

function goScroll(){
  console.count('gogogo');
}

window.addEventListener('scroll', debounce(goScroll, 50));
//debounce的第2個參數可以定義多久毫秒執行1次,若沒填的話此範例預設是每20秒執行1次。

【CSS】卡片翻面效果

<div class="photo">
    <div class="front">第一張卡片</div>
    <div class="back">第二張卡片</div>
</div>
.front {
  width: 300px;
  height: 350px;
  backface-visibility: hidden;
  transition: 0.6s;
  transform-style: preserve-3d;
  position: absolute;
  top: 0;
  left: 0;
  background-color: red;
}
.back {
  width: 300px;
  height: 350px;
  backface-visibility: hidden;
  transition: 0.6s;
  transform-style: preserve-3d;
  position: absolute;
  top: 0;
  left: 0;
  transform: rotateY(-180deg);
  background-color: green;
}
.photo:hover .back {
  transform: rotateY(0deg);
}
.photo:hover .front {
  transform: rotateY(180deg);
}

Class add and remove

此寫法為達成以下目的(常應用於選單收合)

  • A開啟時,點了B,打開B時要順便收起A
  • A開啟時,點了A,要收起A
.box apple
.box orange
.box grape
.box blue
.box gray
.box
 width: 200px
 height: 100px
 background-color: #eee
 text-align: center
 line-height: 100px
 transition-duration: 0.5s
 
.box.teal
 background-color: teal
 color: #fff
const boxes=document.querySelectorAll(".box");

boxes.forEach(box => box.addEventListener("click", checkall)
)

function checkall(){
 const nowTeal=document.querySelector(".teal");
 
 if(nowTeal){
  nowTeal.classList.remove("teal");
 }
 
 if(nowTeal==this){
  this.classList.remove("teal");
 }else{
   this.classList.add("teal");
 }

}

highchart 5角圖

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<div id="container"></div>
#container
 min-width: 400px
 max-width: 600px
 height: 400px
 margin: 0 auto
const spiderData=[
    {
        tag: '住宅',
        value: 5
    },
    {
        tag: '醫療',
        value: 2
    },
    {
        tag: '食品安全',
        value: 5
    },
    {
        tag: '教育',
        value: 1
    },
    {
        tag: '\t',
        value: 0
    },
]

const maxValue=Math.max(...spiderData.map(el => el.value));

Highcharts.chart('container', {

    chart: {
        polar: true,
        type: 'line',
        margin: [40, 0, 0, 0],
    },

    credits: {
        enabled: false
    },

    title: {
        text: ''
    },

    pane: {
        size: '100%'
    },

    exporting: { 
        enabled: false 
    },

    xAxis: {
        categories: spiderData.map((el) => {
            if(el.value===maxValue){
                return `<div style="color: red">${el.tag}<div>`;
            }else{
                return el.tag;
            }
        }),
        tickmarkPlacement: 'on',
        lineWidth: 0,
    },

    yAxis: {
        gridLineInterpolation: 'polygon',
        lineWidth: 0,
        min: 0,
        tickPositions: [0, 1, 2, 3, 4, 5],
        endOnTick: true,
    },

    tooltip: {
        enabled: false,
    },

    series: [{
        showInLegend: false,
        data: spiderData.map(el => el.value),
        pointPlacement: 'on',

    }]

});

CODEPEN

【CSS】字體設定

日文楷體

  • Mac會顯示「游教科書體」
  • Windows會顯示「標楷體」
h1 游教科書あっ!レポートレポート
h1
 font-family: YuKyo-Medium, STKaiti, DFKai-sb
 font-weight: normal

Display

游教科書あっ!レポートレポート

中文襯線體

  • Mac會顯示「宋體-繁」
  • Windows 英數字顯示「News Time Roman」,中文顯示「新細明體」
h1 這是一段中文字查詢頁面
h1
 font-family: 'Songti TC', 'Times New Roman', 'PMingLiu'
 font-weight: normal

Display

這是一段中文字查詢頁面

highchart 儀表圖

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/solid-gauge.js"></script>
<div id="container-speed" class="container"></div>
.container {
  min-width: 310px; 
  max-width: 400px; 
  height: 300px; 
  margin: 0 auto;
}

tspan {
  font-size: inherit;
  color: inherit;
}

.verybad {
  color: #C00000;
  border-color: #C00000;
}

.bad {
  color: #E16100;
  border-color: #E16100;
}

.neutral {
  color: #FFC000;
  border-color: #FFC000;
}

.good {
  color: #D8Bf1A;
  border-color: #D8Bf1A;
}

.verygood {
  color: #9BBB59;
  border-color: #9BBB59;
}

.badge {
  font-size: 12px;
  border: 1px solid;
  border-radius: 3px;
  padding: 1px 2px;
  vertical-align: middle;
}

.voice-num {
  vertical-align: middle;
}
const testData=[43];

var speedOptions={

    chart:{
        type: 'gauge',
        plotBackgroundColor: null,
        plotBackgroundImage: null,
        plotBorderWidth: 0,
        plotShadow: false,
    },
        
    title: {
        text: '網路聲量'
    },
  
    pane: {
        startAngle: -90,
        endAngle: 90,
        background: null
    },
  
    exporting: { 
        enabled: false 
    },
  
    credits: {
        enabled: false
    },
        
    plotOptions: {
        gauge: {
            dataLabels: {
                borderColor: "none",
                useHTML: true,
                style: {
                    fontSize: "20px",
                }
                
            },
            dial: {
                baseLength: '0%',
                baseWidth: 10,
                radius: '100%',
                rearLength: '0%',
                topWidth: 1
            }
        }
    },
           
    // the value axis
    yAxis: {
        labels: {
            y: 10
        },
        tickPositions: [-50, 0, 50],
        minorTickLength: 0,
        min: -50,
        max: 50,
        plotBands: [{
            from: -50,
            to: 50,
            // color: '#C00000', // red
            color: {
                linearGradient: { x1: 0, x2: 1, y1: 0, y2: 0 },
                stops: [
                    [0.2, '#C00000'],
                    // #E16100
                    [0.5, '#FFC000'],
                    //#D8Bf1A
                    [0.7, '#9BBB59'],
                ]
            },
            thickness: '50%'
        }]
    },
    
    series: [{
        name: 'Speed',
        data: testData,
        dataLabels: {
            formatter: function(){
                let badge='';
                switch(true) {
                    case (this.y<-34):
                        //-35 -36 -37
                        badge='非常負面';
                        break;
                    case (this.y<-4):
                        //-34 -33 -32 ... -5
                        badge='較負面';
                        break;
                    case (this.y<5):
                        //-4 -3 ... 3 4
                        badge='中立';
                        break;
                    case (this.y<35):
                        //5 6 ... 33 34
                        badge='較正面';
                        break;
                    case (this.y<50):
                        badge='非常正面';
                }
            
                return `${this.y}分 ${badge}`
            }
        }
    }],
 
    tooltip: {
        enabled: false,
    },
 
};
Highcharts.chart('container-speed', speedOptions);

// -5 ~ +5 中立
// 5 ~ 35  較正面
// 35 ~ 50 非常正面

CODEPEN