Skip to content

Instantly share code, notes, and snippets.

@jialinhuang00
Last active March 16, 2018 01:53
Show Gist options
  • Save jialinhuang00/130fc8eed0e50d8e50bbbb43037dacfd to your computer and use it in GitHub Desktop.
Save jialinhuang00/130fc8eed0e50d8e50bbbb43037dacfd to your computer and use it in GitHub Desktop.
Javascript筆記

前言

  • Iteration methods:會每一個element都給他see一次,every()、filter()、forEach()、map()、some()

  • Accessor methods:不會更動陣列本身,只是呈現你想呈現的,lastIndexOf()、indexOf()

  • Mutator methods:push() pop() unshift() shift()

Methods

漂亮寫法

fill it,參考

new Array(3).fill(null)
// [ null, null, null ]

new Array(5+1).join('0').split('')
// ["0", "0", "0", "0", "0"]
new Array(5+1).join('0').split('').map(parseFloat)
// [0, 0, 0, 0, 0]

Array.from(Array(3), () => 0)
// [0, 0, 0]
Array.from(Array(10), (d, i) => d)
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],透過index

copy,參考

// Highest performance for deep copying literal values
arr2 = arr1.slice();

// Any of these techniques will deep copy literal values as well,
//   but with lower performance.
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = $.extend(true, [], arr1); // jQuery.js needed
arr2 = _.extend(arr1); // Underscore.js needed
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = copy(arr1); // Custom-function needed - as provided above
arr2 = [].concat(arr1)
arr2 = [...arr1]

Array.from()召喚陣列

Array.from('foo')
// ["f", "o", "o"]

Array.isArray()

return true

Array.isArray([])
Array.isArray([1])
Array.isArray(new Array())

特別一點:Array.prototype itself is an array:

Array.isArray(Array.prototype) 

return false

Array.isArray()
Array.isArray({})
Array.isArray(null)
Array.isArray(undefined)
Array.isArray(17);
Array.isArray('Array')
Array.isArray(true)
Array.isArray(false)
Array.isArray({ __proto__: Array.prototype })

Array.of()沒幹啥

Array.prototype.concat()攤平

const num1 = [[1]]
const num2 = [2, [3]]
const nums = num1.concat(num2)
console.log(nums) //[[1], 2, [3]]

num1[0].push([4])
console.log(nums) //[ [ 1, [ 4 ] ], 2, [ 3 ] ]

Array.prototype.copyWithin(replacedEle, begyes, endno)

[1, 2, 3, 4, 5].copyWithin(-2);
// [1, 2, 3, 1, 2]
[1, 2, 3, 4, 5].copyWithin(0, 3);
// [4, 5, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(0, 3, 4);
// [4, 2, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(-2, -3, -1);
// [1, 2, 3, 3, 4]
[].copyWithin.call({length: 5, 3: 1}, 0, 3);
// {0: 1, 3: 1, length: 5}

Array.prototype.entries()

const arr = ['a', 'b', 'c']
const eArr = arr.entries()
console.log(eArr.next().value) // [0, 'a']
console.log(eArr.next().value) // [1, 'b']
console.log(eArr.next().value) // [2, 'c']

// 若用for… of迴圈
const arr = ['a', 'b', 'c']
const eArr = arr.entries()
for (let e of eArr) {
  console.log(e)
}

Array.prototype.every()

function isBigEnough(element, index, array) {
  return element >= 10
}
[12, 5, 8, 130, 44].every(isBigEnough)   // false
[12, 54, 18, 130, 44].every(isBigEnough) // true

Array.prototype.fill()

[1, 2, 3].fill(4)                // [4, 4, 4]
[1, 2, 3].fill(4, 1)             // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2)          // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1)          // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2)        // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN)      // [1, 2, 3]
Array(3).fill(4)                 // [4, 4, 4]
[].fill.call({ length: 3 }, 4)   // {0: 4, 1: 4, 2: 4, length: 3}

Array.prototype.filter()

const arr = [
  { id: 15 },
  { id: -1 },
  { id: 0 },
  { id: 3 },
  { id: 12.2 },
  { },
  { id: null },
  { id: NaN },
  { id: 'undefined' },
  { id: undefined },
  { id: 24 },
]


let invalidEntries = 0
function isNumber(obj) {
  return obj !== undefined && typeof(obj) === 'number' && !isNaN(obj)
}
function filterByID(item) {
  if (isNumber(item.id)) return true
  invalidEntries++
  return false
}
const arrByID = arr.filter(filterByID)
console.log('Filtered Array\n', arrByID) 
console.log('Number of Invalid Entries = ', invalidEntries)

Array.prototype.find()

const inventory = [
    {name: 'apples', quantity: 2},
    {name: 'bananas', quantity: 0},
    {name: 'cherries', quantity: 5}
];
function findCherries(fruit) { 
    return fruit.name === 'cherries'
}
console.log(inventory.find(findCherries)) 
// { name: 'cherries', quantity: 5 }

function isPrime(element, index, array) {
  let start = 2
  while (start <= Math.sqrt(element)) {
    if (element % start++ < 1) return false
  }
  return element > 1
}
console.log([4, 6, 8, 12].find(isPrime)) // undefined, not found
console.log([4, 5, 8, 12].find(isPrime)) // 5

Array.prototype.findIndex()

缺點是只會回傳第一個符合的,find()也是

function isPrime(element, index, array) {
  let start = 2
  while (start <= Math.sqrt(element)) {  
    if (element % start++ < 1) return false
  }
  return element > 1
}
console.log([4, 6, 8, 12].findIndex(isPrime)) // -1, not found
console.log([4, 6, 7, 12].findIndex(isPrime)) // 2

Array.prototype.forEach()

function logArrayElements(element, index, array) {
  console.log('a[' + index + '] = ' + element)
}
// Notice that index 2 is skipped since there is no item at
// that position in the array.
[2, 5, , 9].forEach(logArrayElements)
// logs:
// a[0] = 2
// a[1] = 5
// a[3] = 9

Array.prototype.includes(searchElement, fromIndex)

const arr = ['a', 'b', 'c'];
arr.includes('c', 3)   //false
arr.includes('c', 100) // false

Array.prototype.indexOf(searchElement, fromIndex)

const indices = []
const array = ['a', 'b', 'a', 'c', 'a', 'd']
const element = 'a'
let idx = array.indexOf(element)

while (idx !== -1) {
  indices.push(idx)
  idx = array.indexOf(element, idx + 1)
}
console.log(indices)
// [0, 2, 4]

Array.prototype.join()

const a = ['Wind', 'Rain', 'Fire']
a.join();      	// 'Wind,Rain,Fire'
a.join(', ')  	// 'Wind, Rain, Fire'
a.join(' + ') 	// 'Wind + Rain + Fire'
a.join('');    	// 'WindRainFire

Array.prototype.keys()

注意,object.keys()可忽略沒有的東西,但arr.keys()不行

var arr = ['a', , 'c']
var sparseKeys = Object.keys(arr)
var denseKeys = [...arr.keys()]
console.log(sparseKeys) 	// ['0', '2']
console.log(denseKeys)	  	// [0, 1, 2]
//  , ,
arr[1] == null //true
arr[1] == undefined  //true
arr[1] === undefined  //true
arr[1] === null //false
arr[1] === '' //false
// ,'',
arr[1] == null //false
arr[1] == undefined  //false
arr[1] === undefined  //false
arr[1] === null //false
arr[1] === '' //true

Array.prototype.lastIndexOf(who, fromWhere)

倒著找

cosnst numbers = [2, 5, 9, 2];
numbers.lastIndexOf(2)	 	// 3
numbers.lastIndexOf(7)     	// -1
numbers.lastIndexOf(2, 3)  	// 3
numbers.lastIndexOf(2, 2)  	// 0
numbers.lastIndexOf(2, -2) 	// 0
numbers.lastIndexOf(2, -1) 	// 3

Array.prototype.map()

const kvArray = [
	{ key: 1, value: 10 },
	{ key: 2, value: 20 },
	{ key: 3, value: 30 },
]
const reformattedArray = kvArray.map((obj) => {
	const rObj = {}
	rObj[obj.key] = obj.value
	return rObj
})

const map = Array.prototype.map
const a = map.call('Hello World', x => { 
  return x.codePointAt(0)
})
// a now equals [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]

const numbers = [1, 4, 9];
const doubles = numbers.map((num) => num * 2)
// doubles is now [2, 8, 18]
// numbers is still [1, 4, 9]
doubles

Array.prototype.pop()

const myFish = ['angel', 'clown', 'mandarin', 'sturgeon']
const popped = myFish.pop()
console.log(myFish)   // ['angel', 'clown', 'mandarin' ] 
console.log(popped)   // 'sturgeon'

Array.prototype.push()

回傳數量length

const sports = ['soccer', 'baseball'];
const total = sports.push('football', 'swimming');
console.log(sports); // ['soccer', 'baseball', 'football', 'swimming']
console.log(total);  // 4

Array.prototype.reduce()

const total = [ 1, 2, 3, 4 ].reduce(
  ( acc, cur ) => acc + 2 * cur);
// 19

Array.prototype.reduceRight()

倒過來reduce

const total = [ 1, 2, 3, 4 ].reduceRight(
  ( acc, cur ) => acc + 2*cur);
// 16

Array.prototype.reverse()

const a = ['one', 'two', 'three'];
const b = a.slice() 
const reversed = a.reverse(); 
console.log(a)         	// ['three', 'two', 'one']
console.log(reversed)  	// ['three', 'two', 'one']
console.log(b)         	// ['one', 'two', 'three']

Array.prototype.shift()

const words = ['one', 'two', 'three', 'four']
words.forEach((word) => {
  console.log(word)
  if (word === 'two') words.shift()
})
// one
// two
// four

words
// [ 'two', 'three', 'four' ]

const myFish = ['angel', 'clown', 'mandarin', 'surgeon']
const shifted = myFish.shift()
console.log(myFish)  	// ['clown', 'mandarin', 'surgeon']
console.log(shifted) 	// angel

Array.prototype.slice(beginYes, endNo)

const fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']
const citrus = fruits.slice(1, 3)
// fruits contains ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']
// citrus contains ['Orange','Lemon']

function sortArgs(...args) {
  args = [].slice.call(args)
  console.log(args.length)
  console.log(args.sort())
}
sortArgs("c", "d", /*x*/9, "x")
// 4
// [ 9, 'c', 'd', 'x' ]

Array.prototype.some()

function isBiggerThan10(element, index, array) {
  return element > 10
}
[2, 5, 8, 1, 4].some(isBiggerThan10)  	// false
[12, 5, 8, 1, 4].some(isBiggerThan10) 	// true

const fruits = ['apple', 'banana', 'mango', 'guava'];
function checkAvailability(arr, val) {
  return arr.some(arrVal => val === arrVal);
}
checkAvailability(fruits, 'kela');   // false
checkAvailability(fruits, 'banana'); // true

Array.prototype.sort()

const mixedNumericArray = ['80', '9', '700', 40, 1, 5, 200]

function compareNumbers(a, b) {
  return a - b
}
//下面這個compare走相反路線
function compare(a, b) {
  if (a < b) return 1;   //1代表往後走
  
  if (a > b) return -1
  
  // a must be equal to b
  return 0;
}

console.log('Sorted:', stringArray.sort());
stringArray.sort(compare) === stringArray.sort().reverse()
// true

mixedNumericArray.sort()
// [ 1, 200, 40, 5, '700', '80', '9' ]

mixedNumericArray.sort(compare)
// [ '9', '80', '700', 200, 40, 5, 1 ]
mixedNumericArray.sort(compareNumbers)
// [ 1, 5, '9', 40, '80', 200, '700' ]

Array.prototype.splice(start, deleteCount, item1…)

const myFish = ['angel', 'clown', 'trumpet', 'sturgeon']
const removed = myFish.splice(0, 2, 'parrot', 'anemone', 'blue')
// myFish is ["parrot", "anemone", "blue", "trumpet", "sturgeon"] 
// removed is ["angel", "clown"]

Array.prototype.unshift()

const arr = [1, 2];
arr.unshift(0); // 3
// arr is [0, 1, 2]
arr.unshift(-2, -1); // = 5
// arr is [-2, -1, 0, 1, 2]
arr.unshift([-3]);
// arr is [[-3], -2, -1, 0, 1, 2]

Array.prototype.values()

const arr = ['a', , 'c'];
const sparseKeys = Object.values(arr);  (ok)
const denseKeys = [...arr.values()];  
console.log(sparseKeys); // ['a', 'c']
console.log(denseKeys) 跑不出來!
  1. Array.prototype.toLocaleString()
  2. Array.prototype.toSource()
  3. Array.prototype.toString()

'💩' U+1F4A9 分解 > \uD83D\uDCA9

String.fromCharCode()

String.fromCharCode(65, 66, 67)  
// "ABC"

String.fromCharCode(0xD83D, 0xDCA9)  
// '💩

// 返回失敗
String.fromCharCode(0x1F4A9) 
//"奇怪的框框",只可惜只能小於4位元

String.fromCodePoint() ES6改良版

String.fromCodePoint(0x1F4A9)  // '💩' U+1F4A9

String.prototype.charAt()

'💩'.charAt(0)
//只顯示第一個 "\uD83D"

String.prototype.charCodeAt()

返回10進位的編碼

'💩'.charCodeAt(0)
//55357

// 變成16進位,但和`charAt()`只有返回第一個
'💩'.charCodeAt(0).toString(16) 
//\uD83D

String.propotype.codePointAt()

ES6改良版

String.prototype.codePointAt()
// '💩'.codePointAt(0) // 0x1F4A9

String.propotype.concat()

const hello = 'Hello, '
console.log(hello.concat('Kevin', ' have a nice day.'))
/* Hello, Kevin have a nice day. */
"".concat({}) 		        // [object Object]
"".concat([]) 		        // ""
"".concat(null) 		      // "null"
"".concat(true) 		      // "true"
"".concat(4, 5) 		      // "45"
"".concat(Function) 	    //'function Function() { [native code] }'

String.propotype.includes(str[,fromIndex])

const str = 'To be, or not to be, that is the question.'
str.includes('To be')         // true
str.includes('nonexistent')   // false
str.includes('To be', 1)      // false
str.includes('o be', 1)       // true
str.includes('r', 8)          // true

String.prototype.endsWith(str[, length])

length規定斷在哪裡

const str = 'To be, or not to be, that is the question.'
str.endsWith('question.')   // true
str.endsWith('to be')       // false
str.endsWith('to be', 19)   // true'

String.prototype.indexOf(key[, fromIndex])

找不到回傳-1

'Blue Whale'.indexOf('Blue')        // returns  0
'Blue Whale'.indexOf('Whale', 5)    // returns  5
'Blue Whale'.indexOf('Whale', 7)    // returns -1
'Blue Whale'.indexOf('')            // returns  0
'Blue Whale'.indexOf('', 9)         // returns  9
'Blue Whale'.indexOf('', 10)        // returns 10
'Blue Whale'.indexOf('', 11)        // returns 10

key = ""

  • 若小於str.length返回fromIndex

  • >= str.length返回str.length

這句話有幾個e

const str = 'To be, or not to be, that is the question.'
let count = 0
const pos = str.indexOf('e')
while (pos !== -1) {
  count += 1
  pos = str.indexOf('e', pos + 1)
}

另一種

const str = 'To be, or not to be, that is the question.'
var pattern = /e/g
str.match(pattern).length

String.prototype.lastIndexOf(key[, fromIndex])

只是逆向,但關於index或是返回的index都照舊,找不到傳回-1

'canal'.lastIndexOf('a')     // returns 3
'canal'.lastIndexOf('a', 2)  // returns 1
'canal'.lastIndexOf('a', 0)  // returns -1
'canal'.lastIndexOf('c', -5) // returns 0
'canal'.lastIndexOf('c', 0)  // returns 0
'canal'.lastIndexOf('')      // returns 5
'canal'.lastIndexOf('', 2)   // returns 2

String.prototype.localeCompare(compareString[, locales[, options]])

比較字串第一個,小於返回-1,大於返回1,等於返回0

  • locales為地區,有些字元在地區的排列不同。
  • options - sensitivity分為四種
    • base(a ≠ b, a = á, a = A.)
    • case(a ≠ b, a = á, a ≠ A.),管大小寫
    • accent(a ≠ b, a ≠ á, a = A.),管發音
    • variant(a ≠ b, a ≠ á, a ≠ A.)
'a'.localeCompare('c')                  // -1
'check'.localeCompare('against')        // 1
'a'.localeCompare('a')                  // 0
const unsorted = 'update Link Add feature improve Report'.split(' ')
unsorted.sort((a, b) => a.localeCompare(b)) 
//  ["Add", "feature", "improve", "Link", "Report", "update"]

'ä'.localeCompare('a', 'sv', { sensitivity: 'base' }) // 1
'ä'.localeCompare('a', 'de', { sensitivity: 'base' }) // 0

String.prototype.match()

// "\b" means boundary     "\B" means w/o boundary 

'teiajpas'.match(/\Bpas/)
// [ 'pas', index: 5, input: 'teiajpas' ]

'teiajpas'.match(/te\B/)
// [ 'te', index: 0, input: 'teiajpas' ]
'taaaeaaiajpas'.match(/a{2,}/g)
//[ 'aaa', 'aa' ]
"apple, orange,".match( /apple(,)\sorange\1/)
// [ 'apple, orange,', ',', index: 0, input: 'apple, orange,' ]
" ".match( /\s/) 
// [ ' ', index: 0, input: ' ' ]

"  ".match( /\s+/) 
// [ '  ', index: 0, input: '  ' ]

"\"  ".match( /\"/) 
// [ '"', index: 0, input: '"  ' ]

"   ".match( /\s/g) 
// [ ' ', ' ', ' ' ] //組成一個tab一個space,總共三個
const str = 'For more information, see Chapter 3.4.5.1'
const re = /see chapter \d+\.\d*/i 
//'see Chapter 3.4'
const re1 = /see chapter \d+\.(\d*)/i 
// 'see Chapter 3.4','4'
const re2 = /see (chapter \d+(\.\d)*)/i
// 'see Chapter 3.4.5.1', 'Chapter 3.4.5.1','.1'
'febufhioq'.match(/./)      //f
'febufhioq'.match(/...?/)   //feb
'febufhioq'.match(/(f).*/)  //febufhioq

''.match(/.*/)    //''
''.match(/.+/)    //null
''.match(/./)     //null

(.) matches any single character except line terminators: \n, \r, \u2028 or \u2029.

const a = '>///<'.match(/\/\/\//g)
// [ '///' ]
const b = '>///<'.match(/\/*/g)
// [ '', '///', '', '' ]

// 字串有兩個反斜號,問說有沒有match到一個反斜號
const c = '>//\\\\<'.match(/\\/g)
// [ '\\', '\\' ]

const at = '\\\\'
// '/'滿好理解的,但'\'透過函式輸出來的是包括反斜號的意義,如果是直接像at或'\\\\'直接測試會是'\\\\'

String.prototype.padEnd(length[, str])

捕到我要的長度,舊的str保留

'abc'.padEnd(10)            // "abc       "
'abc'.padEnd(10, "foo")     // "abcfoofoof"
'abc'.padEnd(6, "123456")   // "abc123"
'abc'.padEnd(1)             // "abc"

String.prototype.padStart(length[, str])

承上,相反

'abc'.padStart(10)         // "       abc"
'abc'.padStart(10, "foo")  // "foofoofabc"
'abc'.padStart(6,"123465") // "123abc"
'abc'.padStart(8, "0")     // "00000abc"
'abc'.padStart(1)          // "abc"

String.prototype.repeat()

'abc'.repeat(-1)   // RangeError
'abc'.repeat(0)    // ''
'abc'.repeat(1)    // 'abc'
'abc'.repeat(2)    // 'abcabc'
'abc'.repeat(3.7)  // 'abcabcabc' (當作3次)
'abc'.repeat(1/0)
// RangeError: repeat count must be less than infinity and not overflow maximum string size
// 有個物件有toString()以及repeat()兩種properties
({ toString: () => 'abc', repeat: String.prototype.repeat }).repeat(2)
// 'abcabc'
({ toString: () => 'abc', repeat: String.prototype.repeat }).toString()
// 'abc'
// 'abcabc' (repeat() is a generic method)

String.prototype.replace()

const str = 'Twas the night before Xmas...'
const newstr = str.replace(/xmas/i, 'Christmas')
// Twas the night before Christmas...
// 無論大小寫,原本的str是'xmas'or'Xmas'都可以被換掉

String.prototype.search()

const str = "hey JudE"
const re = /[A-Z]/g
const re2 = /[.]/g
console.log(str.search(re)) 
// 4

// 注意,不是/./
console.log(str.search(re2)) 
// returns -1 cannot find '.' dot punctuation

console.log(str.search(/./g)) 
// 0      

String.prototype.slice(startIndex[, endIndexNo])

可以接受負數,但例如str3 = str1.slice(-2, 4)就不行

const str1 = 'The morning is upon us.' // the length of str1 is 23.
const str2 = str1.slice(1, 8)
const str3 = str1.slice(4, -2)
const str4 = str1.slice(12)
const str5 = str1.slice(30)
    // str2 : he morn
    // str3 : morning is upon u
    // str4 : is upon us.
    // str5 : ""

String.prototype.split()

const names = 'Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ;Chris Hand ';
// 不管有有沒有空格(像是處理資料比較不龜毛),分號作為分水嶺
const re = /\s*;\s*/
const nameList = names.split(re)

console.log(nameList)
/*[ 'Harry Trump',
  'Fred Barney',
  'Helen Rigby',
  'Bill Abel',
  'Chris Hand ' ]*/

String.prototype.startWith()

const str = 'To be, or not to be, that is the question.'
str.startsWith('To be')         // true
str.startsWith('not to be')     // false
str.startsWith('not to be', 10) // true

String.prototype.substr(startIndex[, length])

const str = 'abcdefghij'
str.substr(1)           // bcdefghij
str.substr(-3)          // hij
str.substr(-20, 2)      // ab,負值過大,default 0
str.substr(20, 2)       // '',正值超過長度,空字串

String.prototype.substring(startIndex[, endIndexNo])

index為NaN或小於0,default為0;大於str.length,則default為str.length

前者大於後者,前後index互換;前者等於後者,返回空字串

// str.substring(1, 0) === str.substring(0, 1)
var anyString = 'Mozilla'
anyString.substring(0, 10)        // 'Mozilla'
anyString.substring(4)            //  'lla'

// (-4) -> (0)
anyString.substring(-4)           // 'Mozi'

// (4, -4) -> (4, 0) -> (0, 4)
anyString.substring(4,)           // 'Mozi'

String.prototype.toLowerCase()

'ALPHABET'.toLowerCase()   // 'alphabet'

String.prototype.toUpperCase()

'alphabet'.toUpperCase()   // 'ALPHABET'

String.prototype.toLocaleLowerCase()

String.prototype.toLocaleUpperCase()

String.prototype.toString()

const x = new String('Hello world')

// 實際上是x以物件形式轉為字串
x.toString()
// 'Hello world'


typeof String       // function
typeof String()     // string
typeof new String() // object

String.prototype.trim()

const orig = '   foo  '
orig.trim() // 'foo'

String.prototype.valueOf()

var x = new String('Hello world')
x.valueOf() // Displays 'Hello world'

valueOftoString()比較,參考here以及here

const ob = {ac: 43}

ob.toString()   // '[object Object]'
ob.valueOf()    // {ac: 43}

const nu = '13132'
nu.toString() === nu.valueOf() // true

const n = 4234234
n.valueOf()     // 4234234
n.toString()    // '4234234'


// 是不是加上new有差喔,typeof new XXX會回傳'object'
const date = new Date()

date.toString()
// Thu Mar 15 2018 16:48:32 GMT+0800
date.valueOf()
// 1521103721978
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment