JavaScript 概念三明治(一)

物件 Object

物件是JavaScript 裡面很重要的型別,在其他語言裡的物件可能有不一樣的意思,但在JavaScript裡面,物件就是「一連串鍵與值配對(key-value pairs)的組合」。換句話說,這意味著物件是由一個個的名稱與一個個的對應內容聚集在一起後形成的結果,這個物件的鍵名又被稱為物件的屬性(property),屬性的用途跟變數有一點相像,都是讓開發者在存取時有一個獨特的名稱,用以區別不同內容。

創造一個物件

一個物件最簡單的宣告方式,就是在賦予變數時,用兩個大括號,將即將宣告的物件包裹起來,並用冒號來區分物件內的屬性名稱與想要存放的數值內容。範例如下:

物件屬性的存取

一般的變數在宣告並被賦值後,我們就用該變數名稱來表示要存取對應內容。而這個變數如果存取的內容是物件,則可以搭配中括號「[]」,或是小數點符號「.」來拿到物件裡面某個屬性的內容:

anObject["key1"] --> 用中括號來存取物件屬性的內容
abObject.key1 --> 用小數點符號來存取物件屬性的內容

陣列 Array

陣列在許多程式語言都會出現。它跟物件有一點點像,但是使用的方式有些差異。如同前面提到的,如果物件是一連串的名稱與對應內容組合而成的型別,那麼陣列就是「把一系列的數值放在一起形成的組合」。意即可以先把陣列看成沒有屬性的物件,只是陣列並非像物件那樣是用大括號來宣告。
創造一個陣列
使用中括號就能簡單宣告出一個陣列,並在中括號內用逗點區隔想要存放的各個值,與物件一樣,陣列可以存放多於一個以上的數值。

var array = ["內容一", "內容二"];

與物件屬性可以存放的內容相同,對於陣列裡面可以存放的內容,沒有型別上的限制,想要在陣列裡面放數字、字串、布林、物件或甚至是另外一個陣列,都是可以的。通常存放陣列裡面的數值,我們會用「元素」(element)來稱呼。
存取陣列的元素
存取陣列元素的方法跟物件一樣,可以使用中括號來表示。但是陣列不像物件那樣有明確的屬性可以知道要對哪一個內容作存取,該可麼辦呢?在陣列裡面的處理方式是,既然沒有明確的名稱,那麼就從第一個元素開始,給每一個元素一個足以區別內容的號碼,我們稱之為「索引」(index),陣列的這個號碼,是從0開始算的。
存取陣列的長度
陣列元素的長度可以用.length來取得,它的用法就跟存取物件屬性一模一樣。事實上,陣列背後的實作也是以物件來達成,只是使用的方式不一樣而已。

var array = ["1", "2", "3"];
console.log(array.length);
//3

函式宣告

函式最簡單的使用方式是透過function這個關鍵字來告訴JavaScript你想要宣告的函式。與變數一樣,函式在一般情況下也必須具有名稱才能讓JavaScript知道你想呼叫(執行)哪一個函式。
至於函式執行後回傳的結果則透過return來決定要回傳內容是什麼,而就像前面提到的一樣,return不一定要存在於函式的內容中,只不過如果在函式內沒有任何return被使用,或是有return但後面沒有任何要回傳的值,JavaScript都會自動幫你將回傳的值設置為undefined,所以可以把一個函式回傳的預設值當作是undefined

變數宣告

ES6出現了兩個新的變數宣告的關鍵字,也是目前實際產品開發中最常使用到的兩個語法,它們分別是let以及const。在前面則是用var來處理。
let
let其實與var差不多,與var不同是宣告變數的範疇、以及不能被重複宣告。  var是函式範疇,而let是區塊範疇 

let 是區塊範疇
區塊範疇相比於var的函式範疇,究竟有什麼優缺點呢?一個很明顯的好處就是,能夠更有效避免變數意外地被修改或覆蓋。
var是函式範疇
當我在全域宣告一個變數i,並在後面使用了for迴圈,for迴圈裡面的條件判斷也用到另外一個新的宣告的i,但是你會發現在for條件判斷用i其實在迴圈進行時也無意間對外面的全域變數進行了修改,最後,外面的變數i的內容就跟著變成10。而若使用const和let,這個問題就不會發生。
const和let的範疇則是一樣的,那麼const和let相較起來又有什麼差異呢?
const
const這個字本身意味著常數。它的範疇與let相同,都屬於區塊範疇,但是與let布一樣的是,使用const宣告變數在第一次宣告,並被指派後,就不能修改。也就是說,使用const所宣告的變數,只能夠被讀取。
使用const宣告變數時,一定要跟著一起指派內容。它與var或let不一樣,可以指宣告變數名稱而不給值。若你使用const時這麼做的話,就會出現錯誤。
而上面講到const所宣告的變數無法再重新指派的規則,其實有一個看起來像是例外的情況,那就是當const與物件、陣列一起使用時,會有這樣的情形發生:
看到了嗎?使用const所宣告的變數內容若是物件,則該物件裡的屬性還是能夠被存取跟修改,這看來很像是在對該變數內容作修改,其實並沒有。當變數被宣告並且存放的數值是一個物件時,所帶給變數的並不是物件本身的內容,而是物件存放的記憶體位置。
所以只要該變數所參考的記憶體位置保持一致,就不會有問題。而換另外一個角度來看,若我重新對const所宣告的變數指派另一個物件,那是會報錯的。

圖說演算法使用JavaScript(四)

3-7題目:將句中或片語單字反轉 Reverse Words
給定一個短句,將句子中的每一個單字的字母順序反轉,請注意,是句子中的每個單字,以字做為單位進行字母順序反轉。

JS     reverse_word.js

const change = str =>{
	const answer = [];

	str.split(" ").forEach(word =>{ //注意""有空格
		let temp = "";  //注意""沒空格
		for(let i = word.length-1; i>=0; i--){
			temp +=word[i];
		}
	answer.push(temp);
	});

	return answer.join(" "); //注意""有空格
};

console.log("原來句子:");
console.log("The greatest test of courage on earth is to bear defeat without losing heart.");
console.log("句子中每個單字都反轉:");
console.log(change("The greatest test of courage on earth is to bear defeat without losing heart."));

PHP        reverse_word.php

$my_str="The greatest test of courage on earth is to bear defeat without losing heart.";

function my_reverse ($str){

  $my_arr = explode(" ", $str);
  $len = count($my_arr);
  $i = 0;
  while ($i<=$len-1){
    $t_str[]=strrev($my_arr[$i]);
    $i++;
  }

  $my_re=join(" ",$t_str);
  return $my_re;
}

$my_re = my_reverse($my_str);

echo $my_str."<br>";
echo $my_re;
使用函數:
explode()
count()
join() 或 implode() 把陣列元素组合成的字符串。
strre() 反轉字串
3-8題目:首字大寫 Capitalization
給定一個短句,將句子中的每一個單字的第一個字母轉為大寫,請注意,是每句子中的每一個單字,以字做為單位進行首字大寫轉換。

JS       capitalization.htm

const bigletter = sentence => {
	const words = []; //宣告words陣列

	for (let word of sentence.split(""))
		words.push(word[0].toUpperCase() + word.slice(1));

	return words.join("");
};

console.log("原來的句子");
console.log("Genius is an infinite capacity for taking pains.");
console.log("首字大寫的句子:");
console.log(bigletter("Genius is an infinite capacity for taking pains."));

PHP          capitalization.php  

$my_str="Genius is an infinite capacity for taking pains.";
function my_bigletter ($str){
	$my_arr = explode(" ",$str);
	$my_len = count($my_arr);
	$t_big = array();
	$i = 0;
	
	while ($i<=$my_len-1){
		array_push($t_big, ucfirst($my_arr[$i]));
		$i++;
	}
	
	$f_big = implode(" ", $t_big);
	return $f_big; 
}

$f_bigletter=my_bigletter($my_str);
echo $f_bigletter;
使用函數
explode()
count()
array_push() 将一个或多个元素插入陣列的尾端
implode()
3-9平均值 Mean
給定一個數字組,計算平均值,例如給定的陣列[1,2,3],則回傳平均值為2.0。這支程式可以利用Javascript的reduce()方法,它能將陣列中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。

JS        mean.js

const stat1 = [2,8,7,6,5,6,4];
const stat2 = [9,2,8,7,6,5,6,4];
const reducer = (accu, currentValue) => accu + currentValue;
//2,8,7,6,5,6,4
console.log("第1組原始資料");
console.log("[2,8,7,6,5,6,4]");
console.log(stat1.reduce(reducer)/stat1.length);
//9,2,8,7,6,5,6,4
console.log("第2組原始資料");
console.log("[9,2,8,7,6,5,6,4]");
console.log(stat2.reduce(reducer)/stat2.length);

PHP        mean.php

$my_arr_1=array(2,8,7,6,5,6,4);
$my_arr_2=array(9,2,8,7,6,5,6,4);
echo "數字陣列1:";
print_r($my_arr_1);
echo "<br>";
echo "數字陣列2:";
print_r($my_arr_2);
echo "<br>";
function get_mean ($my_arr){
$len = count($my_arr);$total = array_sum($my_arr);
$mean = $total/$len;return $mean;
}
$my_mean_1 = get_mean($my_arr_1);
$my_mean_2 = get_mean($my_arr_2);
echo "my_mean_1=".$my_mean_1."<br>";
echo "my_mean_2=".$my_mean_2."<br>";
使用函數
count()
array_sum() 計算陣列元素值的總和
3-10回傳給定總和的數值序對 Two Sum
這個函數會傳入兩個引數,第一個引數是一個包含多個數字的整數值,第二個引數為給定的總和值(sum),該函數會回傳所有加總起來會等於給定總和的所有數值序對,這個數值序對內的數字可以多次使用。例如給定的第一個引數為[1,2,2,3,4],給定的第二個引數為數值4,則陣列中的3及1加總結果為4。另一種狀況,陣列中的2及2加總結果為4,則回傳的結果值為[[2,2],[3,1]]。

JS          two_sum.js

const twototal = (num, total) =>{
	const subpair = [];
	const ans = [];
      for (let a of num) {
		const b = total -a;
		if (ans.indexOf(b) !== -1){
			subpair.push([a,b]);
		}
		ans.push(a);
	}
	return subpair;
}
console.log ("第1組原始資料");
console.log ("twototal([1,2,2,3,4], 4)=");
console.log (twototal([1,2,2,3,4], 4));
console.log ("第2組原始資料");
console.log ("twototal([2,3,5,1,5,1,3,4], 6)=");
console.log (twototal([2,3,5,1,5,3,4], 6));
Array.prototype.indexOf() 找出元素索引值的陣列indexOf()
Array.prototype.push() 會將一或多個的值,加入至一個陣列中

PHP          two_sum.php

$arr_1 =array (2,3,5,1,5,1,3,4);
function get_two_sum($arr, $num){
$t_arr = array();
$ans = array();
$len = count($arr);
$i=0;
	while ($i <=$len-1){
		$b = $num - $arr[$i];
		$arr_slice = array_slice($arr, $i+1);
		if (in_array($b, $arr_slice) == true){
			$ans[]=array($arr[$i], $b);
		}
		$i++;
	}
	return $ans;
}
$my_two_sum = get_two_sum($arr_1, 6);
print_r($my_two_sum);
使用函數
count()
arr_slice($arr,$num) 函數切割 $arr陣列、$num從多少開始切
in_array($val,$arr) 在函數中尋找是否有值