由 ianchen0419 發表的全部文章

IIFEs

function statements

function statements在執行前會先透過Hoisting儲存在記憶體,
所以可以提前執行不會有問題。

greeting(); //可以被提前執行

function greeting(){
  console.log('Good');
}

function expressions

function expressions執行前不會進記憶體,
所以提前執行會出問題。

greeting(); //→不會理你

var greeting=function(){
 console.log('GOOD');
}

IIFEs

透過function expressions建立函式,並且立刻執行它。

沒用IIFEs時

var greeting=function(){
 console.log('GOOD'); 
}

//Console Panel
//Nothing

使用IIFEs時

var greeting=function(){
console.log('GOOD'); 
}();
//會立刻執行

//Console Panel
//GOOD

Form相關事件

簡介

埋在form裡面的<input type=”submit” />以及<button>,只要按下就會觸發form執行

reportvalidity()

手動觸發「檢核」提示

form#myForm
 input(type="text" required)
 input(type="submit")
 
button(onclick="myForm.reportValidity()") click me

checkValidity()

檢查表單檢核有沒有過,有通過的話回傳true,沒通過的話回傳false

form#myForm
 input(type="text" required)
 input(type="submit")
//Console Panel
myForm.checkValidity()

reset()

清空表單的input內容

form#myForm
 input(type="text" required)
 input(type="submit")
//Console Panel
myForm.reset() //清空內容

PHP陣列取值

name如果命名成xxx[]的話,傳到PHP會直接變成陣列
適合用在很多checkbox時

<form action="ttt.php" method="post">
    <input type="checkbox" name="user[]" value="草莓" id="strawberry" />
    <label for="strawberry">草莓</label>
    <input type="checkbox" name="user[]" value="橘子" id="orange" />
    <label for="orange">橘子</label>
    <input type="checkbox" name="user[]" value="香蕉" id="banana" />
    <label for="banana">香蕉</label>
    <br>
    <br>
    <input type="submit" name="your_submit" />
</form>

<?php 

if(!empty($_POST['your_submit'])){
  for ($i=0; $i < count($_POST['user']); $i++) { 
    echo $_POST['user'][$i].'<br>';
  }
}

?>

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");
 }

}