1. Object.defineProperty(obj, prop, description)
Parameter
Type
Description
obj
Object
要處理的對象
prop
String
添加 or 修改的屬性名稱
description
Object
添加 or 修改的屬性描述符
Description Prop
Type
Default Value
Description
configurable
Boolean
false
可配置性(修改屬性配置)
enumerable
Boolean
false
可遍歷性
value
any
undefined
值
writable
Boolean
false
可修改性(修改屬性值)
get
Function
undefined
屬性的getter,調用時無參數、this綁定到屬性所屬對象
set
Function
undefined
屬性的setter,調用時無參數、this綁定到屬性所屬對象
value 和 getter, setter 不能同時存在
繼 undefined, null, boolean, string, number, object 六種基本類型後第七種基本類型 Symbol
是一種獨一無二的字符串
var s1 = Symbol ( 'foo' ) ;
var s2 = Symbol ( 'bar' ) ;
s1 // Symbol(foo)
s2 // Symbol(bar)
s1 . toString ( ) // "Symbol(foo)"
s2 . toString ( ) // "Symbol(bar)"
// ES5
function Point ( x , y ) {
this . x = x
this . y = y
}
Point . prototype . toString = function ( ) {
return '(' + this . x + ', ' + this . y + ')'
}
var point = new Point ( 0 , 0 )
// ES6
class Point {
constructor ( x , y ) {
this . x = x
this . y = y
}
toString ( ) {
return '(' + this . x + ', ' + this . y + ')'
}
}
let P = class {
// ...
}
typeof Point // "function"
Point === Point . prototype . constructor // true
// 立即調用
let person = new class {
constructor ( name , id ) {
this . name = name
this . id = id
}
}
class Point {
constructor ( ) {
// ...
}
toString ( ) {
// ...
}
valueOf ( ) {
// ...
}
}
// 等價於 =>
Point . prototype = {
toString ( ) { } ,
valueOf ( ) { }
}
// ES6
class Point {
constructor ( x , y ) {
// ...
}
toString ( ) {
// ...
}
}
Object . keys ( Point . prototype )
// []
Object . getOwnPropertyNames ( Point . prototype )
// ["constructor","toString"]
// ES5
var Point = function ( x , y ) {
// ...
} ;
Point . prototype . toString = function ( ) {
// ...
} ;
Object . keys ( Point . prototype )
// ["toString"]
Object . getOwnPropertyNames ( Point . prototype )
// ["constructor","toString"]
let method = "getArea"
class Square {
[ method ] ( ) {
console . log ( 0 )
}
}
new Square ( ) . getArea ( )
class Foo {
constructor ( ) {
return Object . create ( null )
}
}
new Foo ( ) instanceof Foo // false
class Point {
constructor ( x , y ) {
this . x = x ;
this . y = y ;
}
toString ( ) {
return '(' + this . x + ', ' + this . y + ')' ;
}
}
var point = new Point ( 2 , 3 ) ;
point . toString ( ) // (2, 3)
point . hasOwnProperty ( 'x' ) // true
point . hasOwnProperty ( 'y' ) // true
point . hasOwnProperty ( 'toString' ) // false
point . __proto__ . hasOwnProperty ( 'toString' ) // true
var p1 = new Point ( 2 , 3 ) ;
var p2 = new Point ( 3 , 2 ) ;
p1 . __proto__ === p2 . __proto__ //true
// 同時代表可從一個實例的 __proto__ 擴展一個類
var p1 = new Point ( 2 , 3 ) ;
var p2 = new Point ( 3 , 2 ) ;
p1 . __proto__ . printName = function ( ) { return 'Oops' } ;
p1 . printName ( ) // "Oops"
p2 . printName ( ) // "Oops"
var p3 = new Point ( 4 , 2 ) ;
p3 . printName ( ) // "Oops"
let set = new Set ( )
[ 1 , 2 , 3 , 4 , 5 , 4 , 3 , 2 , 1 ] . map ( x => set . add ( x ) ) // set.add() 添加元素
console . log ( set ) // Set {1,2,3,4,5}
// 以數組做參數
let set = new Set ( [ 1 , 2 , 3 , 4 , 5 , 4 , 3 , 2 , 1 ] )
console . log ( set ) // Set {1,2,3,4,5}
// 基本操作
add ( value ) // 添加,返回Set結構本身
delete ( value ) // 刪除,成功返回true
has ( value ) // 返回布林值,代表是否存在此值
clear ( ) // 清除所有成員
// Set 轉數組
let array = Array . from ( set )
//
// 去除數組重複成員
array = [ ...new Set ( array ) ]
Array . from ( new Set ( array ) )
// 遍歷操作
keys ( ) // 返回鍵名遍歷器
values ( ) // 返回鍵值遍歷器
entries ( ) // 返回鍵值對遍歷器
forEach ( ) // 使用回調函數遍歷成員
// 一般函數
function func1 ( ) { }
const func2 = function ( ) { }
// 箭頭函數
const func3 = ( ) => { }
// 一般函數
const func = function ( ) {
console . log ( this )
}
const obj = { f : func }
func ( ) // Window
obj . f ( ) // obj
// 箭頭函數
const func = ( ) => {
console . log ( this )
}
const obj = { f : func }
func ( ) // Window
obj . f ( ) // Window
// 一般函數
const Person = function ( name , age ) {
this . name = name
this . age = age
}
const person = new Person ( 'john' , 25 )
console . log ( person ) // Person {name: "john", age: 25}
// 箭頭函數
const Person = ( name , age ) => {
this . name = name
this . age = age
}
const person = new Person ( 'john' , 25 )
console . log ( person ) // Uncaught TypeError: Person is not a constructor
// 一般函數
f ( ) // 'function f()'
function f ( ) {
console . log ( 'function f()' )
}
// 箭頭函數
f ( ) // Uncaught ReferenceError: Cannot access 'f' before initialization
const f = ( ) => {
console . log ( 'function f()' )
}
JavaScript為非阻塞(單線程)腳本語言,Web Worker作為多線程替代技術
let ajax = function ( ...args ) {
// ...
return new Promise ( function ( resolve , reject ) {
// ...
let response
resolve ( response )
let error
reject ( error )
} )
}
const a , b , c
ajax ( a , b , c )
// when resolve is triggered
. then ( response => console . log ( response ) )
// when reject is triggered
. catch ( error => console . log ( error ) )
let 沒有副作用,沒有變量提升,有作用域的概念,可完全取代var
'use strict'
if ( true ) {
let x = 'hello'
}
for ( let i = 0 ; i < 10 ; i ++ )
console . log ( i )
'use strict' ;
if ( true ) {
console . log ( x ) ; // ReferenceError
let x = 'hello' ;
}
const 相較於 let 更好(不變性)
全局只聲明const
const 有利於分佈式運算和編譯優化
// bad
var a = 1 , b = 2 , c = 3 ;
// good
const a = 1 ;
const b = 2 ;
const c = 3 ;
// best
const [ a , b , c ] = [ 1 , 2 , 3 ] ;
// bad
const a = "foobar" ;
const b = 'foo' + a + 'bar' ;
// acceptable
const c = `foobar` ;
// good
const a = 'foobar' ;
const b = `foo${ a } bar` ;
const c = 'foobar' ;
const arr = [ 1 , 2 , 3 , 4 ] ;
// bad
const first = arr [ 0 ] ;
const second = arr [ 1 ] ;
// good
const [ first , second ] = arr ;
// bad
function getFullName ( user ) {
const firstName = user . firstName ;
const lastName = user . lastName ;
}
// good
function getFullName ( obj ) {
const { firstName, lastName } = obj ;
}
// best
function getFullName ( { firstName, lastName } ) {
}
// bad
function processInput ( input ) {
return [ left , right , top , bottom ] ;
}
// good
function processInput ( input ) {
return { left, right, top, bottom } ;
}
const { left, right } = processInput ( input ) ;
// bad
const a = { k1 : v1 , k2 : v2 , } ;
const b = {
k1 : v1 ,
k2 : v2
} ;
// good
const a = { k1 : v1 , k2 : v2 } ;
const b = {
k1 : v1 ,
k2 : v2 ,
} ;
// bad
const a = { } ;
a . x = 3 ;
// if reshape unavoidable
const a = { } ;
Object . assign ( a , { x : 3 } ) ;
// good
const a = { x : null } ;
a . x = 3 ;
// bad
const len = items . length ;
const itemsCopy = [ ] ;
let i ;
for ( i = 0 ; i < len ; i ++ ) {
itemsCopy [ i ] = items [ i ] ;
}
// good
const itemsCopy = [ ...items ] ;
// 類數組對象轉數組
const foo = document . querySelectorAll ( '.foo' ) ;
const nodes = Array . from ( foo ) ;