2019年4月29日 星期一

[Back To Basic] Javascript - DOM Navigation

HTML DOM是由節點(nodes)所組成。

節點(nodes)和節點(nodes)之間有階層關係(上下或平行),可以用以下方法來切換節點。


  • parentNode
  • childNodes[nodenumber]
  • firstChild
  • lastChild
  • nextSibling
  • previousSibling

DOM Root Node

可以透過以下兩個方法來取得整個頁面的DOM
  • document.body
  • document.documentElement

屬性: nodeName

  • 永遠是大寫
  • 唯讀
  • HTML元素(elements)節點的nodeName是標籤(tag)名稱
  • HTML屬性(attributes)節點的nodeName是屬性(attributes)名稱
  • 文字節點(text nodes)的nodeName永遠是 #text
  • 文件節點(document nodes)的nodeName永遠是 #document

屬性: nodeValue 

  • HTML元素(elements)節點的nodeValue是null
  • 文字節點(text nodes)的nodeValue是自己本身
  • HTML屬性(attributes)節點的nodeValue是屬性值

屬性: nodeType

會回傳目前節點的類型
  • 1: HTML元素(elements)節點 / ELEMENT_NODE
  • 2: HTML屬性(attributes)節點 / ATTRIBUTE_NODE
  • 3: 文字節點(text nodes) / TEXT_NODE
  • 8: 註解 / COMMENT_NODE
  • 9: 文件節點(document nodes) / DOCUMENT_NODE
  • 10: 文件型態節點 / DOCUMENT_TYPE_NODE

2019年4月28日 星期日

[Back To Basic] Javascript - DOM EventListener

事件監聽(Event Listener)

  • 可以附加處理邏輯(event handlers)到特定的HTML元素(elements)上
  • 不會覆蓋原本存在的事件(events)
  • 可以附加多個事件到同一個HTML元素(element)上
  • 可以附加多個處理邏輯(event handlers)到同一個HTML事件(events)上
  • 可以附加到任意 DOM object 上,e.g. window object
  • 完全分離 HTML 和 javascript,提升可讀性

  • addEventListener(): 新增處理邏輯
  • removeEventListener() 移除處理邏輯

addEventListener()

語法: element.addEventListener(event, function, useCapture);
  • event: 事件名稱,不用加on,e.g. click 不要用 onclick
  • function: 事件發生時,要執行的 function
  • useCapture: true:事件冒泡(event bubbling) / false:事件捕獲(event capturing),預設false(外層先處理,內層後處理)

事件捕獲(event capturing) 和 事件冒泡(event bubbling)

HTML DOM 的事件傳播(event propagation)有兩種,捕獲冒泡

事件傳播(event propagation),定義了事件(events)發生時,元素(elements)的順序。

e.g.

<div>
  <p></p>
</div>

若點擊p時,應該先執行 div 的 click 事件,還是 p 的 click 事件呢?

事件冒泡(event bubbling):內層先處理,外層後處理;p先處理,div後處理

事件捕獲(event capturing):外層先處理,內層後處理;div先處理,p後處理

IE8

addEventListener() 和 removeEventListener() IE9以後都支援。

IE8以前要用 attachEvent 和 detachEvent

var button = document.getElementById("button");
if (button.addEventListener) {     // For all major browsers, except IE 8 and earlier
 button.addEventListener("click", myFunction);
} else if (button.attachEvent) {   // For IE 8 and earlier versions
  button.attachEvent("onclick", myFunction);
}


2019年4月26日 星期五

[Back To Basic] Javascript - DOM Events

javascript 可以和 HTML 的事件(events) 互動。


  • 在HTML中使用 this ,代表該 HTML DOM
e.g.
<div id="demo1" onclick="demo1click(this)">Click me</div>

this代表整個 <div></div>


  • 可在 HTML 上直接加入事件,也可用 javascript 賦予事件
<button onclick="demo2click()">Show Time</button>

<button id="show-date">Show Time !</button>
document.getElementById('show-date').onclick = demo3click;

onload 和 onunload


當進入或離開頁面時,可使用者兩個方法。

2019年4月24日 星期三

[Back To Basic] Javascript - DOM Animate

改變 HTML 和 CSS 都非常容易,試試 animate 吧。

動畫會和時間互動,因此會使用到

  • setInterval(handler, interval)
  • clearInterval(handle)

  • setInterval會回傳一個數字,這個數字是 handler 的代號
  • handler 是一個 function,每隔 interval 毫秒,執行一次。
  • clearInterval 可停止一個 handler,做為結束的用途



source code

2019年4月23日 星期二

[Back To Basic] Javascript - DOM Elements

尋找HTML元素(elements)的方法

  • id
  • tag name
  • class name
  • css selectors
  • HTML object collections

若沒有找到,回傳 null

2019年4月22日 星期一

[Back To Basic] Javascript - HTML DOM Document

找 HTML元素(elements)


  • document.getElementById(id)
  • document.getElementsByTagName(name)
  • document.getElementsByClassName(name)

變更HTML元素(elements)


  • innerHTML
變更內部的HTML元素
  • attribute
變更屬性(attributes)
  • style.property
變更樣式(styles)
  • setAttribute(attribute, value)
變更屬性(attributes)

增刪元素(elements)


  • createElement(element)
新增元素(element)
  • removeChild(element)
刪除元素(element)
  • appendChild(element) 
附加元素(element)
  • replaceChild(new, old)
替換元素(element)
  • write(text)
附加文字

新增事件(events)


element.event() = function(){...}
e.g.
button.onclick() = function(){
  console.log('click');
}


2019年4月21日 星期日

[Back To Basic] Javascript - DOM Methods

HTML DOM 方法(methods)是可以在HTML元素(elements)上執行的行為

HTML DOM 屬性(properties)是可以在HTML元素(elements)上存取或變更的

改變id="demo1"的內容:

document.getElementById('demo1').innerHTML = 'Test';

  • getElementById 是方法
  • innerHTML 是屬性

[Back To Basic] Javascript - HTML DOM(Document Object Model)

什麼是DOM


DOM是一個W3C(World Wide Web Consortium)的標準。

DOM定義了訪問文件(documents)的標準:

W3C DOM 是一個平台和中立語言介面,允許程式和腳本動態訪問、更新文件的內容、架構及樣式。

原文:
"The W3C Document Object Model (DOM) is a platform and language-neutral interface that allows programs and scripts to dynamically access and update the content, structure, and style of a document."

W3C DOM 標準被拆分為3個部分
  • Core DOM
  • XML DOM
  • HTML DOM

什麼是 HTML DOM


當頁面被載入時,瀏覽器會建立頁面的DOM(Document Object Model)。

HTML DOM 被建構成一個樹狀物件(Objects)。

因此,有了物件模型(object model),javascript 有能力創造動態的HTML

  • javascript 可以增刪修所有HTML元素(elements)
  • javascript 可以增刪修所有HTML屬性(attributes)
  • javascript 可以增刪修所有HTML CSS外觀(styles)
  • javascript 可以增刪修所有HTML 事件(events)

2019年4月18日 星期四

[Back To Basic] Javascript - Function Closures

閉包(Closures)


  • javascript 變數只有全域變數和區域變數二種
  • 閉包(closures)可以讓全域變數變成區域變數

function 和 變數的關係


  • function 可以使用所有在內部宣告的變數
  • function 也可以使用所有在外部宣告的全域變數
  • 不使用 var 宣告的變數,一律被視為全域變數,無論在 function 內或外

問題


  • 用全域變數記

var count = 0;
function myAdd1() {
    var count = 0;
    count += 1;
}

myAdd1();
myAdd1();
myAdd1();
var show = count1; // count 想要顯示 3, 但結果 count = 0, 因為這邊的 count 是全域變數

  • 用區域變數記

function myAdd2() {
    var count = 0;
    count += 1;
    return count;
}
var show = myAdd2(); // count 想要顯示 1,2,3..., 但結果 count = 1,1,1...

解決步驟

  • 1. 建立巢狀 function,額外形成,上下關係作用域
function myAdd3() {
    var count = 0;
    function plus() {
        count += 1;
    }
    plus();
    return count;
}
var myAdd4 = (function () {
    var count = 0;
    return function () {
        count += 1;
        return count;
    }
})()
myAdd4(); // count = 1
myAdd4(); // count = 2
myAdd4(); // count = 3

說明

宣告 var myAdd4 為立即函式時
  • count = 0 立刻執行,且只執行一次
  • myAdd4 被指定為 
function () {
    count += 1;
    return count;
}
  • 使用 myAdd4(),仍然可以變更 count 的值 <--- 這一連串的設計方式被稱為閉包
  • 也讓 count 成功地變成 private 變數
  • count 被 匿名函式的作用域(the scope of the anonymous function) 保護起來 <--- 目的達成
閉包特性: 閉包是一個,可以在父作用域(parent scope)被關閉時持續訪問(access)的 function


2019年4月17日 星期三

[Back To Basic] Javascript - Function apply()

apply()

  • 可以藉由 apply()達成: 一個方法(method),給不同物件(objects)使用
  • 跟call()很像

apply() 和 call() 不同之處

傳入參數; apply()為一個陣列, call()的各自分開

Strict Mode

myObj.myMethod.apply(null, [1, 2, 3]);

不是嚴格模式 this = window object
嚴格模式 this = null

2019年4月16日 星期二

[Back To Basic] Javascript - Function call()

call()

  • 可以藉由 call()達成: 一個方法(method),給不同物件(objects)使用
  • 內建在 javascript 的 method 中
  • 讓A物件可以使用B物件的方法
  • 可以傳入參數

2019年4月15日 星期一

[Back To Basic] Javascript - Function Invocation

函式調用(Function Invocation)

  • 定義 Function 時,並不會執行 Function
  • 調用函式時,才會執行 Function
  • 直接定義函式,預設此函式為全域物件的函式
  • 全域物件(global object)通常是 HTML頁面或是瀏覽器的 window
  • 盡量別在全域定義 function,很容易撞名
  • 全域的 this = window object

不要用 window object 來當變數,系統很容易壞掉

使用物件(object)中的函式(function)時,this代表該物件(object)

建構式調用(constructor invocation)

調用函式時,在前面加一個 new 關鍵字,就是建構式調用(constructor invocation)

function myFunction3(x, y) {
    this.x = x;
    this.y = y;
    console.log(this); // this 要在被 new 的時候才知道是什麼 
}

var myObj = new myFunction3(2, 3); // 看似新增一個function 其實是新增了一個 object

myObj.x; // 2

[Back To Basic] Javascript - Function Parameters

function parameters 特性
  • 不定義資料型態
  • 不檢查傳入參數的型別
  • 不檢查傳入參數的數量
  • 沒傳的參數值: undefined

預設值

// ECMAScript 2015
function myFunction(a = 1, b = 2) { }

arguments

function 中內建 arguments 的物件,包含所有傳入參數的資訊

function myFunction(a = 1, b = 2) {
    let i = 0;
    let sum = 0;
    for (i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}
  • 若傳入參數(arguments)比宣告參數(parameters)還多,可用arguments取得
  • 傳值(by value): 改變傳入參數(arguments)時並不會改變傳入前原本的變數值
  • 但如果傳入參數(arguments)是物件(object),改變物件屬性值時,原本的值也會跟著改變

2019年4月11日 星期四

[Back To Basic] Javascript - Function

Function 宣告(Declarations) v.s. Function 表達式(Expressions)

  • Function 宣告(Declarations)

function myCount1(x, y) {
    return x * y;
}
  • Function 表達式(Expressions)
var myCount2 = function (x, y) { return x * y };

  1. 表達式有分號結尾,因為它是一個可執行的陳述式
  2. 表達式的寫法是"匿名(anonymous) function",不需要 function name,因為在使用使用時用變數的名字即可

Function Hoisting

Function 宣告(Declarations),也有  Hoisting 的特性
但是Function 表達式(Expressions),沒有

匿名自我呼叫函式(anonymous self-invoking function)

特性:
  • function 會立即執行
  • 獨立擁有作用域,可避免檔案過大時,使用變數時和全域變數衝突
(function () {
  // 這個函式會立即執行
})();

Function 根本上是物件(Object)

  • typeof function(){}是 function
  • functions 也擁有屬性(properties)和方法(methods)
  • 當 function 成為 object的屬性(properties)時,稱之為方法(methods)
  • 當 function 被設計為建立物件時(objects)時,稱之為物件建構式(object constructor)

Arrow Functions

ES6的語法,有更簡潔的方式來撰寫 Function 表達式(Expressions)
特性:
  • 沒有自己的 this
  • 因此不適合用來定義物件方法(object methods)
  • 沒有 Hoisting 的特性
  • 盡量使用 const 宣告

2019年4月10日 星期三

[Back To Basic] Javascript - Object ECMAScript 5

ECMAScript 5新增了很多物件方法(Object Methods)

var user = {
    name: 'Shawn',
    age: 18,
    language: 'zh-tw'
};

  • 變更屬性值
語法: Object.defineProperty(object, property, {value : value});
Object.defineProperty(user, 'language', { value: 'en' });
  • 變更中繼資料(Meta Data)
中繼資料共有五種
  1. writable: 屬性 value 是否可寫入
  2. enumerable: 屬性可否可被列舉
  3. configurable: value以外的屬性可否重新配置
  4. get: Getter
  5. set: Setter
Object.defineProperty(user, 'language', { writable: false });
user.language = '123'; // 無作用

Object.defineProperty(user, 'language', { enumerable: false });
Object.keys(user); // 不可列舉 language, 所以沒有 language

Object.defineProperty(user, 'language', { configurable: false });
Object.defineProperty(user, 'language', { get: function () { return language } }); // 無作用
  • 取得所有屬性(properties)
語法: Object.getOwnPropertyNames(object);
Object.getOwnPropertyNames(user); // 可取得所有屬性,包括 enumerable = false 的屬性
  • 列舉所有屬性(properties)
語法: Object.keys(object);
Object.keys(user);
  • 取得特定屬性的中繼資料(Meta Data)
語法: Object.getOwnPropertyNames(object);
JSON.stringify(Object.getOwnPropertyDescriptor(user, 'name')); // 取得 name 的中繼資料
  • 取得物件的prototype
語法: Object.getPrototypeOf(object);
function Person(name, age, language) {
    this.name = name;
    this.age = age;
    this.language = language;
};
var user2 = new Person('Koji', 20, 'jp');
console.log(Object.getPrototypeOf(user2)); // 用 log 才看的到
  • 禁止新增屬性到物件中
語法: Object.preventExtensions(object);
Object.preventExtensions(user2);
Object.defineProperty(user2, 'nationality', { value: 'tw' }); // 無作用
  • 取得該物件是否可新增到屬性
語法: Object.isExtensible(object);
Object.isExtensible(user2); // false
  • 密封物件,讓物件屬性不可變更
語法: Object.seal(object);
Object.seal(user2);
user2.phone = '0900123456';
document.getElementById('demo8').textContent = JSON.stringify(user2); // phone 未加入
  • 取得該物件是否被密封
語法: Object.isSealed(object);
Object.isSealed(user2);
  • 凍結整個物件(包含值)
語法: Object.freeze(object);
Object.freeze(user2);
user2.name = 'test';
user2.name; // 不會被改成test
  • 取得該物件是否被凍結
語法: Object.isFrozen(object);

2019年4月9日 星期二

[Back To Basic] Javascript - Object Prototypes

所有的物件(Objects),都繼承了 prototype 的屬性(properties)和方法(methods)。
  • Date 繼承 Date.prototype
  • Array 繼承 Array.prototype
  • Person 繼承 Person.prototype
  • 繼承鏈的最頂端是 Object.prototype

在 prototype 增加屬性(properties)或方法(methods),會影響到所有已經存在的物件(objects)

function User(name, age, phone) {
    this.name = name;
    this.age = age;
    this.phone = phone;
}

var me = new User('Shawn', 18, '0900123456');
var coworker = new User('Koji', 20, '0911321321');

// 所有使用者增加國籍的屬性
User.prototype.nationality = 'Taiwan';

// 所有使用者增加取得出生年份的方法
User.prototype.birthYear = function () {
    var year = new Date().getFullYear();
    return year - this.age;
}

me.nationality; // Taiwan
coworker.nationality; // Taiwan
me.birthYear();
coworker.birthYear();

不要修改 javascript 標準物件的 prototype

2019年4月8日 星期一

[Back To Basic] Javascript - 物件建構式(Object Constructor)

使用建構式

function User(name, age, phone) {
    this.name = name;
    this.age = age;
    this.phone = phone;
}

var me = new User('Shawn', 18, '0900123456');
var coworker = new User('Koji', 20, '0911321321');

新增屬性(property)到物件中

me.nationality = 'Taiwan';

新增方法(method)到物件中

coworker.birthYear = function () {
    var year = new Date().getFullYear();
    return year - this.age;
}

新增屬性(property)到建構式中

新增方法(method)到建構式中(只能在一開始的時候給予,不可用新增屬性的方式)

function UserType2(name, age, phone) {
    this.name = name;
    this.age = age;
    this.phone = phone;
    this.nationality = 'Taiwan';
    this.changeName = function (name) {
        this.name = name;
    }
}

source code

2019年4月7日 星期日

[Back To Basic] Javascript - 物件存取(Object Accessors)

  • 物件存取(Object Accessors)
  • 別名 getter and setter
  • ECMA 5 推出

Getter and Setter

var user = {
    name: 'Shawn',
    firstName: 'Tseng',
    age: 18,
    get fullName() {
        return this.name + ' ' + this.firstName;
    },
    set setFirstName(firstName) {
        this.firstName = firstName;
    }
}

var fullNameNode = document.createTextNode(user.fullName);
var demo1 = document.getElementById('demo1');
demo1.appendChild(fullNameNode);

user.setFirstName = 'Sanada';
var fullNameNode = document.createTextNode(user.firstName);
var demo2 = document.getElementById('demo2');
demo2.appendChild(fullNameNode);

Function vs Getter

get fullName() {
        return this.name + ' ' + this.firstName;
}
function fullName() {
        return this.name + ' ' + this.firstName;
}
有何不同?
使用的時候:
user.fullName; // 語法較輕便
user.fullName();

Object.defineProperty()

Object.defineProperty() 中也可使用 Accessors

2019年4月2日 星期二

[Back To Basic] Javascript - Object Methods

在 function 中使用 this

method 是物件(object)的屬性(property),這個屬性定義了一個 function
var user = {
    name: 'Shawn',
    getName: function () {
        return this.name;
    }
}

  • 使用 function
user.getName()
  • 取得 property
user.getName

可視為可執行的 function,也可視為 object 的 property

新增 function


user.attachPrefix = function (prefix) {
    return prefix + ' ' + this.name;
}

2019年4月1日 星期一

[Back To Basic] Javascript - Object Property

  • 屬性(Properties)是和物件(Objects)相關的值
  • 屬性(Properties)可以被新增、修改、刪除
  • 屬性(Properties)有一些是唯讀的

for...in

逐一針對物件的每個屬性進行邏輯處理


var user = { name: 'Shawn', age: 18 };
for (const key in user) {
    if (user.hasOwnProperty(key)) {
        const element = user[key];
    }
}

新增屬性(add property)

user.dept = 'mkpl';

刪除屬性(delete property)

  • delete 會刪除屬性和屬性值
  • delete 只適用於屬性
  • 若屬性不存在,使用 delete 系統會壞掉
delete user.age;

屬性(Property)的屬性(Attribute)

Property 除了 Property value 以外,還有其他的 Attribute
  • enumerable
  • configurable
  • writable