Try   HackMD

JavaScript 函式的補充

無論如何會接收參數或環境變數

ruby 會檢查參數數量

def foo(x, y, z)
end

# foo(1, 2, 3)
foo(1, 2)

js02.rb:1:in `foo': wrong number of arguments (given 2, expected 3) (ArgumentError)

js: 完全不檢查參數數量

給多的就當作沒看見

function foo(x, y, z) {
  console.log("x: ", x);
  console.log("y: ", y);
  console.log("z: ", z);
}

// foo(1, 2, 3)
foo(1, 2, 3, 4, 5, 6)

result

x:  1
y:  2
z:  3

少給的部分是undefined

function foo(x, y, z) {
  console.log("x: ", x);
  console.log("y: ", y);
  console.log("z: ", z);
}

// foo(1, 2, 3)
foo(1, 2)
x:  1
y:  2
z:  undefined

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

為了知道按下btn按鈕時,發生什麼事,會帶event進來

function clickHandler(event) {

}
document.getElementById('btn').addEventListender('click', clickHandler);

clickHandler(event)

Eg. 輸入帳號密碼

document.getElementById('btn').addEventListender('keydown', function(evt) {
  console.log(evt)
});

跟鍵盤有關的事件
keydown: 連續按下不放
keypress: 按下去再放開
keyup

Eg. 輸入帳號,按下enter才出現輸入密碼欄位

  $("#user_account").keydown(function (event) {
    if (event.which == 13 && $(this).val().length > 0){
        if ($('#user_account').val().toLowerCase() == 'new'){
          window.location.href = '/users/sign_up';
        } else {
          $("#p_password").show();
          $("#user_password").focus();        
        }
    } else {
      $("#p_password").hide();
    }
    
  });

closure 閉包

Ref
MDN

ruby

# This is RUBY!!!!
variable = 1

def foo(x, y, z)
  p variable
end

foo(1, 2, 3)

ruby拿不到外面的變數

js 拿得到

let variable = 100;

function bar() {

  console.log(variable)
}
bar() // 100

但是變數名稱剛好一樣的話,裡面的會遮住外面的

let variable = 100;

function bar() {
  let variable = 999;
  console.log(variable)
}
bar() // 999

ruby

ary = [1, 2, 3, 4, 5]
# first = ary[0]
# second = ary[1]
# third = ary[2]
first, second, third = ary
p first
p third

Destructive assignment

解構賦值- JavaScript | MDN

js設計好的地方:把結構拆到變數裡去

let ary = [1, 2, 3, 4, 5];
let [first, second, third] = ary;
console.log(third) // 3
let [head, ...tails] = ary;
console.log(head); // 1
console.log(tails); // [ 2, 3, 4, 5 ]

(但是ruby沒有設計hash的Destructive assignment)

js 的object

let student = {name: 'john', age: 13, gender: 'M'};
// let studentName = student.name;
// let studentAge = student.age;
let {name: studentName, age: studentAge} = student;
// 右邊是整包資料

//let {name: studentName, age: studentAge} = {name: 'john', age: 13, gender: 'M'};
console.log(studentName); // john
console.log(studentAge); // 13

語法糖

如果變數與值名稱一樣,冒號以及之後的東西可以省略

//let {name: name, age: age} = student;
let {name, age} = student;

console.log(name);
console.log(age);

pattern match 是destructive assignment的進階版
(又可以給值、又可以比對)

進階版

let student = {name: 'john', age: 13, gender: 'M'};

function baz({name, gender}) {
  console.log(name); // john
  console.log(gender); // M
}
// let student = {name: 'john', age: 13, gender: 'M'};

baz(student) 

實務上的應用: 把{target: {keyCode}}拿出來用(剝洋蔥剝出自己要的部分)

document.getElementById('btn')
        .addEventListender('keydown', function({target: {keyCode}}) {
          console.log(keyCode)
          // console.log(evt)
        });

範例

<body>
  <input type="text" name="name" id="name" class="inputCol">
  <input type="password" name="pw" id="password" class= "inputCol">
  <button id="btn">Login</button>

  <script>
    document.querySelector('inputCol').addEventListener('keypress', event =>{
      console.log('event');
    })
    document.querySelector('#btn').addEventListener('click',()=>{
      alert('login!!!');
    })
  </script>
</body>

按下enter,跳到password

先綁事件,查enter的keycode

按下1, 然後enter

srcElement,可以調到自己的id

focus 關注的地方

輸入完帳號、密碼後,才可以enter送出

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <input type="text" name="name" id="name" class="inputCol">
  <input type="password" name="pw" id="password" class="inputCol">
  <button id="btn">Login</button>

  <script>
    const ENTER = 13;
    for(let el of document.querySelectorAll('.inputCol')) {
      el.addEventListener('keypress', (event) => {
        let {keyCode, srcElement} = event;
        if (keyCode === ENTER) {
          checkInputAndLogin(srcElement.id);
        }
      })
    }
    
    function checkInputAndLogin(srcElementId) {
      if (srcElementId === 'name') { 
        document.getElementById('password').focus();
        return; 
      }
      if (srcElementId !== 'password') { return; }
      let nameVal = document.getElementById('name').value;
      let pwVal = document.getElementById('password').value;
      if (nameVal && pwVal) {
        document.getElementById('btn').click();
      }
    }

    document.querySelector('#btn').addEventListener('click', () => {
      alert('login!!!!')
    })

  </script>
</body>
</html>

陣列的屬性與方法

.fruits.length => 屬性,沒有括號

.fruits.join() => 方法

indexOf()

let names = ['apple', 'banana', 'cherry'];
let joinedNames = names.join('\n');
console.log(joinedNames);

let indexOfCherry = names.indexOf('cherry'); // 2
console.log(indexOfCherry);


let indexOfCherry = names.indexOf('water');
// -1 無論如何回傳都是數字,不用再做其他的判斷( nul or undifined)
console.log(indexOfCherry);

concat()

不會改變原來的陣列

let names = ['apple', 'banana', 'cherry'];
let fruits1 = ['watermelon', 'pear']
let allFruits = names.concat(fruits1);
console.log(allFruits);
console.log(names);
console.log(fruits1);

FIFO (queue) vs LIFO (stack)

frutis.pop()
fruits.shift()

fruits.push('pear')
fruits.unshift('grape')

迭代

for of

forof
很像array但不是array
這些資料撈出來有順序,但是沒有辦法用array的其他方法

let iterable = 'boo';

for (let value of iterable) {
  console.log(value);
}
// "b"
// "o"
// "o"

鍵值對

set

set和 array的差別 => 裡面的值不能重複

Turple (元組)

其他語言(如python)內建

優點: 省記憶體

let priceByCountry = {
  'tw': 300,
  'us': 10.2,
  'jp': 1250,
}

// 如何換成array?
// Object.entries
let result = Object.entries(priceByCountry)
console.log(result)
//[ [ 'tw', 300 ], [ 'us', 10.2 ], [ 'jp', 1250 ] ]
let result = Object.entries(priceByCountry)
                   .map(tpl => [tpl[0], tpl[1] * 1.05])

// object 轉成entries
let newPrice = Object.fromEntries(result)
console.log(newPrice) 
// { tw: 315, us: 10.709999999999999, jp: 1312.5 }

其他不同的資料結構

let cat = {
  name: 'mimi',
  age: 3,
  eat: function() { console.log('好吃!') }
 }
// 當系統有大量物件,為了不要浪費記憶體,js會使用prototype
 cat.eat() // 好吃