顯示具有 Javascript 標籤的文章。 顯示所有文章
顯示具有 Javascript 標籤的文章。 顯示所有文章

2016-11-21

JavaScript 5 新增了 9 個 Array Methods

JavaScript 正式的名稱為 EcmaScript(以下稱 ES),在 ES 5 時新增了 9 個 Array 相關的 method:
  • forEach
  • map
  • filter
  • every
  • some
  • reduce
  • reduceRight
  • indexOf
  • lastIndexOf

這些新 method 有一些共通點:

  • 可以傳入兩個參數,第一個為必要的 function,第二個為非必要的 calling context。
    • 會依序對 Array 裡每個值呼叫該 function。
    • 如果 Array 裡有空格,則會跳過不執行傳入的 function。
    • 會傳入三個參數到該 function 裡。
      • Array 裡輪到的值
      • 輪到值在 Array 裡的 index
      • 整個 Array:唯一可以修改 Array 的地方
    • function 回傳的值會「影響」Array method 回傳的值,但不是每個 method 都會有回傳值。
    • calling context 就是作為第一個 function 參數的執行主體,也就是 function 裡 this 指向的物件。
  • 這些 Array method 原則上不會修改 Array 內容,除非是對第一個傳入參數 function 裡的第三個參數(整個 Array,上面紅字處)進行操作。
  • 這些共通點,大部分 method 都有,但不是每個都有。

2015-12-31

Javascript 的 instance property 與 static property

Javascript 的 instance property 很容易實做,只要用 this 就可以了。
function Counter() {
  this.count = 1;
}

var c1 = new Counter();
console.log(c1.count++); // 1
console.log(c1.count++); // 2
console.log(c1.count++); // 3

var c2 = new Counter();
console.log(c2.count++); // 1
console.log(c2.count++); // 2
console.log(c2.count++); // 3
但是 static property 就有點傷腦筋了,先來看正常的部份,將 property 直接掛在 prototype 上,改了其中一個 instance 的 prototype property,其他 instance 的 prototype property 也跟著改變,表示是共用同一個物件,可以視為 static property。
Counter.prototype.date = new Date();

console.log(c1.date); // Thu Dec 31 2015 22:18:39 GMT+0800 (台北標準時間)
console.log(c2.date); // Thu Dec 31 2015 22:18:39 GMT+0800 (台北標準時間)

c1.date.setFullYear(2000); // 改了 c1.date,c2.date 也連帶受影響
console.log(c1.date); // Sun Dec 31 2000 22:19:25 GMT+0800 (台北標準時間)
console.log(c2.date); // Sun Dec 31 2000 22:19:25 GMT+0800 (台北標準時間)
除了上面的 Date 格式,陣列也有一樣的效果。
Counter.prototype.array = [];

c1.array.push(1);
c1.array.push(2);
console.log(c1.array); // [1, 2]

c2.array.push(3);
c2.array.push(4);
console.log(c2.array); // [1, 2, 3, 4]
接下來是傷腦筋的地方,在 int 格式變數的修改不會影響其他 instance。
Counter.prototype.integer = 0;
c1.integer = 1;
console.log(c1.integer); // 1
console.log(c2.integer); // 0
字串格式也是不會影響其他 instance。
Counter.prototype.string = 'a';
c1.string = 'b';
console.log(c1.string); // b
console.log(c2.string); // a
書上網路上找不到解答,只能自己猜測。

應該是 reference 的關係,數值和字串在 Javascript 是 pass by value,而物件格式的 Date 與陣列則是 pass by reference。

所以透過 prototype 來實做的 static property 只能算是半套,再想想囉。
---
---
---

2015-12-29

Javascript 的 private property

前面提過,可以用 this 儲存 instance property,但是 instance property 完全沒有安全性可言
function User(account, password) {
  this.account = account;
  this.password = password;
}
var u = new User('Neil', 'yule');
console.log(u.account); // 可以讀到帳號
console.log(u.password); // 密碼走光了
u.password = 'yuching'; // 更慘,密碼被駭了
console.log(u.password);
那要怎麼保護密碼呢?不可以用 instance property 儲存敏感資料

先來看看 Javascript function 特性,從下面的例子,在 User 外面,也就是從 User instance 是拿不到 password 和 secret 的。
function User(account, password) {
  this.account = account;
  // this.password = password;
  var secret = 'yule'; // 外面看不到 password 和 secret
}
var u = new User('Neil', 'yule');
console.log(u.password); // undefined
console.log(u.secret); // undefined

2015-12-25

Javascript 的 new

我們知道 Javascript function 有兩種呼叫方式,一種是直接呼叫,另一種是透過 new 呼叫,兩種呼叫方式有什麼差別呢?就我目前所知,有兩個差異。

第一個差異是 this 是誰?

2015-05-03

Javascript 的 prototype

這裡沒有討論 Javascript 到底是不是一個物件導向的語言,只想去瞭解一下 Javascript 的 prototype 是什麼以及怎麼用。

拿物件導向的 Java 來比較一下,倒是一個不錯的出發點。

Java 用的是 class(類別),Javascript 用的是 prototype(原型)。

Java 是靜態的,Javascript 是動態的。

Java 有多型與繼承,Javascript 也有。

多才多藝的 function


Javascript 的 function 有很多種用法,可以是一般的 fucntion,也可以是 constructor(建構函式)。

2015-04-27

Javascript 的 caller 屬性

有些書說隱藏版屬性 arguments 有個 caller 屬性,但我怎麼也找不到,倒是在 Function 裡找到這個屬性。

官方定義 caller:呼叫目前正在執行的 function 的 function,簡言之就是,誰呼叫這個 function。
function a() {
  return a.caller === b; // 一定要用 function name 去呼叫 caller
}
function b() {
  return a();
}
console.log(b()); // true
caller 主要用途是追蹤呼叫堆疊,即追蹤 function invoke chain。

2015-04-26

Javascript 的 callee 屬性

每個 function 裡都有個叫做 arguments 的隱藏版屬性,所謂隱藏版屬性就是不用定義或宣告,立即可用。

arguments 多半用來處理可變參數數量的情況。
function a(b, c) {
  return b + c;
}
console.log(a(2, 3)); // 5

function a() {
  var b = 0;
  for (var i=0; i<arguments.length; i++) { // 隱藏版屬性,憑空出現
    b += arguments[i];
  }
  return b;
}
console.log(a(2, 3)); // 5
console.log(a(2, 3, 4)); // 9
console.log(a(2, 3, 4, 5)); // 14
arguments 除了可以用來讀取傳入 function 的參數外,還有一個特別的屬性,就是 callee。

2015-01-21

Effective Javascript #12 - 變數拉升 Variable Hoisting

又解了一個謎團,Javascript 的區域變數(Local Variable)是 Function-scoped,而非  Block-scoped。

用程式說明。
function hoist(i) {
  console.log('input - ' + i);
  for (var i=0; i<5; i++) {
    console.log('loop - ' + i);
  }
  console.log('return - ' + i);
  return i;
}
hoist(3);
傳入 i = 3,第一行輸出 input - 3,沒有問題。

然後進入迴圈,重新命名 i,從 0 加到 4,因而輸出 loop - 1 ~ 4,這也可以理解。

問題在 return 應該是多少?

按照 Block-scoped 概念,應該是 return - 3,錯!

2014-07-23

jQuery Checkbox 全選與取消全選

會有這篇筆記,一切都是起因於 jQuery 1.6 做了一些衝動的事:改寫了 attr(...) 的用法,詳情太囉唆,請看以下網址:

jQuery 1.6.1上場救援,不用改寫attr()囉
jQuery 1.6 .attr() 和 .prop()

也就是我習慣用的 attr(...) 變得很奇怪,尤其在控制 checkbox 的勾與不勾時,行為非常詭異,詭異到我不想去了解發生了什麼事。

解法很簡單,改用 prop(...) 就好了。
// 勾選或取消「全選」時,checkbox 的 checked 屬性(prop)跟著 checkboxAll 走就可以
$('.checkboxAll').click(function(){
  $('.checkbox').prop('checked', $('.checkboxAll').prop('checked'));
});
// 單獨勾選或取消 checkbox 時,須同步狀態到 checkboxAll 
$('.checkbox').click(function(){
  var checkedLength = $('.checkbox:checked').length;
  var checkboxLength = $('.checkbox').length;
  $('.checkboxAll').prop('checked', checkedLength == checkboxLength);
});
prop(...) 只會回傳 true 或 false,不會回傳空字串、undefined 或 checked,事情變得簡單多了。
---
---
---

2014-03-13

Responsive Web Design

Responsive Web Design?

智慧型手機的興起讓瀏覽網頁的螢幕變小,但既有網頁多半是固定寬度,一開始手機瀏覽器都是將網頁縮小到可以放進那小小的螢幕裡,但是這種作法一點幫助也沒有,圖那麼小、文字那麼小,什麼都看不清楚,只能在那不斷的放大放大縮小縮小,頭都暈了,怎麼上網呢?

那為了手機另外做一個網站可以嗎?是不是只要有錢有時間就可以,其實不然,不只是建置的時間,還有維護的時間都要加倍,最大的問題是,給手機用的網頁寬度要設多少呢?桌機從七百多像素到將近一千像素都有(15吋到近30吋的螢幕),桌機小螢幕遇到大網頁挺多滑鼠拉一拉就好了,那手機呢?三吋、四吋、五吋到六吋的螢幕都有,甚至還有十幾吋的平板,這光是網頁寬度就訂不出來了,寬度訂小了,大螢幕很痛苦,訂的大了,小螢幕又沒滑鼠可以拉,這條路還走得下去嗎?

那有沒有可能一套網頁通吃呢?其實是有可能的,這就是 Responsive Web Design 的目的。

Responsive Web Design 組成

Responsive Web Design 由三種 CSS 技術組成:
  • Media Query
  • Fluid Layout
  • Flexible Images
從技術的名稱可以想像 Responsive Web Design 的內容,以 Media Query 決定使用不同的 Fluid Layout,並輔以不同的 Flexible Images

2014-02-07

jQuery 與 Quirks Mode

最近遇到的問題,$(window).width()$(window).height() 都回傳 0,但只限於 IE 某些版本,PM 最後鎖定是 Quirks Mode 才會有的問題。

Google 後發現,jQuery 1.8.1 以後就不支援 Quirks Mode 了

嗯,先了解一下什麼是 Quirks Mode,維基百科這麼說,嗯,有看沒有懂,再翻成中文看一次,有點概念,到底能不能講人話啊。

最後得到的理解是:
  • 相對於 Quirks Mode,有一個 Standard Mode(標準模式)。
  • Standard Mode 指的是瀏覽器完整支援 HTML/CSS,而 Quirks Mode 則是在標準出現以前,或者說 HTML/CSS 成為標準以前,各家瀏覽器各自表述的情形。
  • 然後當 HTML/CSS 成為標準,且各家瀏覽器開始完全支援時,在這之前已經開發的網頁怎麼辦?
  • 瀏覽器為了向前相容,所以切成兩種模式,也就是 Standard Mode 與 Quirks Mode。
  • 遇到舊的網頁就用 Quirks Mode 顯示,遇到新的網頁就用 Standard Mode 顯示。
  • 那怎麼區分新舊網頁呢?加上 DOCTYPE 就是新網頁,預設就會用 Standard Mode 顯示,舊的網頁沒有 DOCTYPE 就會用 Quirks Mode 顯示。
小結一下我遇到的問題:
  • 沒有加上 DOCTYPE  的網頁被舊版 IE 以 Quirks Mode 顯示。
  • 然後不小心用了新版的 jQuery。
  • 所以$(window).width()$(window).height()都回傳 0。
可能的解法:
  • 改用 jQuery 1.8.1 以前的版本。
  • 為網頁加上 DOCTYPE,記得要加在網頁的最最最前面,在 DOCTYPE 之前不能有任何字元,不然貼心的 IE 就會自動進入怪異模式(Quirks Mode)。
<!DOCTYPE html>
<html>...</html>
---
---
---

2014-01-19

Clickable Div in IE

Clickable Div

想要做一個隱形連結,例如在一張圖片上有兩個位置可以點,直覺想到可以用兩個absolutediv 放上去想要的位置,然後為 div 加上 click listener。
<style type="text/css">
.div {
  position: absolute;
  border: 1px solid white;
  cursor: pointer;
  width: 70px;
  height: 165px;
}

.divA {
  top: 30px;
  left: 60px;
}

.divB {
  top: 30px;
  left: 280px;
}
</style>
<div style="background-image: url('clickable.jpg'); width: 400px; height: 275px;">
  <div class="div divA" onclick="alert('Click A');"></div>
  <div class="div divB" onclick="alert('Click B');"></div>
</div>
嗯,在 chrome 與 IE 各版本(ie7 - ie11)都沒問題。

2014-01-05

HTML5 與 CSS3 的偵測器 - Modernizr 2.7.1

自從 Firefox 與 Chrome 打破 IE 獨大後,接著智慧型手機在瀏覽器市場帶來更大的衝擊,不只是各家爭鳴,還各版橫行,加上 HTML 5 與 CSS3 帶來許多嶄新的功能,讓網頁開發變得更有挑戰,也更頭大。
「這個新功能很炫,但是可以用了嗎?瀏覽器支援了嗎?」
這是網頁開發一定會遭遇的問題,幸好 Firefox 與 Chrome 更新速度很快,而且常常(偷偷的)自動更新,比較沒有這些問題,但是 IE 就不是這麼一回事了,尤其是一堆舊的 IE 遲遲不願更新的情況,讓 IE 一直是網頁設計最大的挑戰,IE 真的為網頁設計帶來許多就業機會啊!

Modernizr 是什麼?

官方定義如下:
「Modernizr is a JavaScript library that detects HTML5 and CSS3 features in the user’s browser.」
重點如下:
  • Javascript 程式
  • 用來偵測
  • 瀏覽器是否支援 HTML5 與 CSS3 功能
Modernize 的功能如下:
  • 用來偵測使用者的瀏覽器是否支援想要使用的功能。
  • 適合用來做 Progressive Enhancement。
  • 在頁面載入時立即執行所有偵測(可以自訂偵測項目),並將偵測結果放在一個 Javascript 物件(Modernizr)供 Javascript 程式使用,再另外增加 CSS class 到 HTML 物件(html)上供 CSS 使用。
  • 目前可以測試超過 40 個功能,而且厲害的是只需要幾毫秒的時間。
  • 整合 yepnope.js 做條件式載入,有關 yepnope 請參考 yepnope.js 讓瀏覽器只載入需要的檔案 與 More in yepnope 1.5.4

2014-01-04

More in yepnope 1.5.4

前一篇筆記「yepnope.js 讓瀏覽器只載入需要的檔案」只提到條件式載入,這邊再來看看 yepnope 還有哪些功能。

官方定義

yepnope is an asynchronous conditional resource loader that's super-fast, and allows you to load only the scripts that your users need.
歸納的重點如下:
  • 非同步的方式
  • 依據指定的條件
  • 超快的
  • 載入所需的檔案

2013-12-27

yepnope.js 讓瀏覽器只載入需要的檔案

yepnope.js 有很多功能,這邊想用的是「條件式載入」。

條件式載入?

以不支援陣列 indexOf() 的 IE8  為例(真弱),以前的作法是先載入再判斷要不要用。

2012-10-26

Javascript 與 Java Applet 合作

以前只知道可以用 Javascript 呼叫 Java Applet,但都沒有動機去嘗試,今天有了。

Javascript 不能讀寫本機的檔案,這是可以確定的,另外能不能執行本機的程式(例如 ipconfig),大概也不行吧,而這些 Java 都可以!

合作的原理很簡單,在 Applet 所在的 HTML 裡,Javascript 可以呼叫 Applet 帶來的 Java class,至於為什麼可以呼叫,這個我還不知道,就先擱下吧。

2012-09-19

LimeJS 在迴圈的 callback 裡傳值

這問題不會只發生在 LimeJS 上,只是 LimeJS 需要多一點的處理。

先看看標準的錯誤方式。
for (...) {
 var fKey = ...;
 var friend = new lime.Sprite()...; 
 $(friend.getDeepestDomElement()).click(function(){
  // 會得到很怪的 fKey
  // 所有的 click 都會得到同一個 fKey
  // 通常應該是迴圈中最後一個物件的 fKey
  alert(fKey);
 });
}
再來就是正確的方式。
for (...) {
 var fKey = ...;
 var friend = new lime.Sprite()...; 
 // friend 本身不是 Dom 物件,不能用來藏值
 $(friend.getDeepestDomElement()).attr('fKey', fKey);
 $(friend.getDeepestDomElement()).click(function(){
  // 在迴圈的 callback 裡讀值,一定得透過 this
  var fKey = $(this).attr('fKey');
  alert(fKey);
 });
}
---

2012-07-09

用 jQuery 種一顆簡單樹(Tree)

小時候要用 Javascript 做一個下面這種樹狀圖,應該要報個幾十個人天吧。

如果再加上右鍵功能,嗯,「PM,請給我幾個人月吧」!



最大的問題應該出在瀏覽器相容性,以及少了一些很好用的 function 吧。

這些問題 jQuery 都解決了,所以今天種一顆樹簡單多了。

What is "this" Javascript?

這是我摸索 Javascript this 的過程。

Javascript Variable, Property, and Parameter

其實這篇筆記要紀錄的是我對 function context  最後的一塊拼圖,就是 function call object,快速的從頭說起...

在 top-level 可以宣告變數(variable)與屬性(property),就是存在 function 以外的變數。
var globalVariable = 'Global variable';
this.globalProperty = 'Global property';
window.windowProperty = 'Window property';
function a() {...};
在 top-level,this 就是指 window,特別的是,變數與屬性可以混用,下面三種用法都是指同一個變數。
neil.log(globalVariable); // global variable 與 property 互通
neil.log(this.globalVariable);  // 這個用法得在 top-level 才有效
neil.log(window.globalVariable); 
那進到 function 之後呢?