找回密碼
 註冊
搜索
查看: 173|回復: 0

[分享] JavaScript 函式(Function)

[複製鏈接]
發表於 3 天前 | 顯示全部樓層 |閱讀模式
Push to Facebook
箭頭函式(arrow function, lambda function)
基本用法


// 基本寫法,沒有參數的時候要記得加上空括號
let greeting = () => {
  return 'Hello';
};

// 如果只有一行,可以省略{ }
let greeting = () => console.log('Hello');

// 如果只是要回傳某個值,可以省略 { } 和 return,但是需要在一行內寫完。
let greeting = () => 'Hello';

// 如果要直接回傳某個物件,要多用 () 包起來
let greeting = ({ name }) => ({ name });

// 當函數只有一個參數時,不需要使用括號
let greeting = (person) => 'Hello ' + person;

// 兩個以上的參數,需要使用括號
let add = (a, b) => a + b;



對 this 的影響
在箭頭函數中,this 指稱的對象在所定義時就固定了,this 會和 instance object 綁定,而不會隨著使用時的脈絡而改變(An arrow function is bound to its parent scope):
// 傳統函式寫法 this 會隨著呼叫的脈絡而改變。
// 使用箭頭函式時,不論什麼時候執行函式,this 會和 instance object 綁定。

var Person = function (data) {
  for (var key in data) {
    this[key] = data[key];
  }
  this.getKeys = function () {
    return Object.keys(this);
  };
};

var Alena = new Person({ name: 'Alena', role: 'Teacher' });

console.log(Alena.getKeys()); // 'this' refers to 'Alena'

var getKeys = Alena.getKeys;
console.log(getKeys()); // 'this' refers to the node process




函式預設值(function default value)

基本用法
function add(x = 3, y = 5) {
  console.log(x + y);
}

add(); // 8




觀念
丟入的參數值會由前往後代入:
// 只給後面的變數預設值,則可以代入一個參數就好
let add_with_last_para = (a, b = 3) => a + b;
add_with_last_para(2); // 5
add_with_last_para(5, 2); // 7

// 只給前面的變數預設值,後面沒代入的參數會變 undefined
// 如果第一個參數想要代入預設值,可以用 undefined
let add_with_first_para = (a = 3, b) => a + b;
console.log(add_with_first_para(2)); // NaN (a = 2, b = undefined)
console.log(add_with_first_para(undefined, 4)); // 7




因此把需要預設值的參數放在最後一個:
/* Always put default parameters last. @ airbnb 7.9 */
// bad
function handleThings(opts = {}, name) {...}

// good
function handleThings(name, opts = {}) {...}




若帶入的參數為物件,則可參考以物件為參數帶入函式中
不要改變傳入的參數
不要試圖改變函式參數的值(例如,使用傳統賦予函數預設值的方式),這是有副作用的(side-effect)、可能會導致無預期的 bug ,並且降低效能:
Use default parameter syntax rather than mutating function arguments. @airbnb 7.7
// really bad
function handleThings(opts) {
  opts = opts || {}
  opts = 'a'
  if (!a) { a = 1; }
  // ...
}

// good
function handleThings(opts = {}) { ... }
function f3 (a) {
  const b = a || 1;
}




Never mutate parameters @ airbnb 7.12
// bad
function f1(obj) {
  obj.key = 1;
}




函式的常用方法Function.prototype.call()

/**
*   fun.call(thisArg[, arg1[, arg2[, ...]]])
*   你可以在呼叫一個現存的函數時,使用不一樣的 this 物件。 this 會參照到目前的物件。
*   不同處只有 call() 接受一連串的參數,而 apply() 單一的array作為參數
**/

fn.call(<thisArg>, <arg1>, <arg2>);




取得函式所有的參數使用展開語法(spread syntax)

keywords: get all parameters value in function
  • 不要使用 arguments 作為參數名稱,arguments 是保留字(@airbnb 7.5)
  • 如果需要取得所有輸入的參數內容,使用 ... rest syntax,因為透過 ... 取得的是真實的陣列:

// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  return args;
}

// good
function concatenateAll(...args) {
  // args 會是一個陣列
  return args;
}

concatenateAll('car', 54, 'tree'); // [ 'car', 54, 'tree' ]




以物件為參數帶入函式中

方法一:使用物件的解構賦值
let person = {
  name: 'Anna',
  age: 56,
  job: { company: 'Tesco', title: 'Manager' },
};

function greetWithSpreadOperator({ age, name, job: { company, title } }) {
  var yearOfBirth = 2018 - age;
  console.log(`${name} works at ${company} as ${title} and was born in ${yearOfBirth}.`);
}

greetWithSpreadOperator(person); // Anna works at Tesco as Manager and was born in 1962.




可以帶入預設值

let person = {
  name: 'Aaron',
  age: 29,
};

function greet({ name, age, interestLevel = 5 } = {}) {
  console.log(`Your name is ${name}, and age is ${age}. Your interest level is ${interestLevel}.`);
}

greet(person); // Your name is Aaron, and age is 29. Your interest level is 5.
greet(); // 如果沒有在參數的地方使用 = {},則當沒有帶入任何東西時會直接爆掉




方法三:在函式中取出參數

// 方法三: 在函式中取出參數(較舊的方法)
let person = {
  name: 'Anna',
  age: 56,
  job: { company: 'Tesco', title: 'Manager' },
};

greetWithObjectAsOption(person);

function greetWithObjectAsOption(person) {
  let name = person.name;
  let age = person.age;
  let job = person.job;
  console.log(
    `Your name is ${name}, and your age is ${age}. You work in ${job.company} as ${job.title}.`,
  );
}




Code Style定義函式:

使用 function declaration
  • 由於 Function declarations 具有變數提升(hoisted)的特性,因此建議在定義變數的時候使用 Function expression(@ airbnb 7.1):

// bad
function foo () {...}

// bad
const foo = function () {...}

// good: 前面定義使用時的函式名稱(簡短),後面的名稱可描述此函式的作用
const short = function longUniqueMoreDescriptiveLexicalFoo () {...};
short();   // call the function




  • 風格:

// bad
const f = function () {};
const g = function () {};
const h = function () {};

// good
const x = function () {};
const y = function a() {};




使用 IIFE
@ airbnb 7.2
// immediately-invoked function expression (IIFE)
(function () {
  console.log('Welcome to the Internet. Please follow me.');
})();




不要在 non-function block 中定義函式
@ airbnb 7.3, 7.4
不要在 if, while, 等等非函式的區塊中定義函式,這可能導致問題。如果有在其中定義函式的需要,則先定義一個變數,再把函式給它:
// bad
if (currentUser) {
  function test() {
    console.log('Nope.');
  }
}

// good
let test;
if (currentUser) {
  test = () => {
    console.log('Yup.');
  };
}




匿名函式建議使用 arrow function
@airbnb 8.1
// good
[1, 2, 3].map((x) => {
  const y = x + 1;
  return x * y;
});

https://pjchender.dev/javascript/js-function/



您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則

Archiver|手機版|小黑屋|TShopping

GMT+8, 2025-5-24 12:06 , Processed in 0.023016 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回復 返回頂部 返回列表