2021年11月18日 星期四

JavaScript 的 call、apply、bind

call、apply、bind:將物件變成另一個函式中的this

[測試範例的 物件 和 函式]
物件:var objTest
函式:function test(a, b)

var objTest = {
  x: "xyz"
}

function test(a, b) {
  console.log("this.x=", this.x);
  console.log("a=", a);
  console.log("b=", b);
  console.log("arguments=", Array.from(arguments));
  //console.log("arguments=", [...arguments]);
}
test(1, 2);
//this.x= undefined
//a= 1
//b= 2
//arguments= [1, 2]


[call]
使用call,會直接執行function。
test.call(objTest);
//this.x= xyz
//a= undefined
//b= undefined
//arguments= []

test.call(objTest, 10);
//this.x= xyz
//a= 10
//b= undefined
//arguments= [10]

test.call(objTest, 10, 20);
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]


[apply]
使用apply,會直接執行function。跟call不同,傳入的參數為陣列。
test.apply(objTest);
//this.x= xyz
//a= undefined
//b= undefined
//arguments= []

test.apply(objTest, [10]);
//this.x= xyz
//a= 10
//b= undefined
//arguments= [10]

test.apply(objTest, [10, 20]);
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]


[bind]
使用bind,會回傳綁定後的function,綁定時可選擇是否綁定參數值,沒綁定的參數值,可使用時再傳入。
//只綁定this物件
var ff = test.bind(objTest);
ff();
//this.x= xyz
//a= undefined
//b= undefined
//arguments= []

ff(10);
//this.x= xyz
//a= 10
//b= undefined
//arguments= [10]

ff(10, 20);
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]
//綁定了this物件,和第一個參數a=10,則使用時,參數a不須也無法再傳值,a固定為10
var ff = test.bind(objTest, 10);
ff();
//this.x= xyz
//a= 10
//b= undefined
//arguments= [10]

ff(20); //已綁定了第一個參數a=10,所以剩下的參數只剩一個,此處傳的是b=20
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]

ff(50, 60); //多傳的參數60,不會用到
//this.x= xyz
//a= 10
//b= 50
//arguments= [10, 50, 60]
//綁定了this物件,和第一個參數a=10,第二個參數b=10,則使用時,參數a、參數b不須也無法再傳值,a固定為10,b固定為20
var ff = test.bind(objTest, 10, 20);
ff();
//this.x= xyz
//a= 10
//b= 20
//arguments= [10, 20]

ff(91, 92);
//this.x= xyz
//a= 10
//b= 20
//arguments= (4) [10, 20, 91, 92]



[應用]
  • 處理偽陣列(類似陣列,但不是陣列的資料,當成陣列處理)
    function aa() {
      //arguments 不是陣列,不能使用 slice、push...
      //arguments.slice(1)
      //Uncaught TypeError: arguments.slice is not a function
      console.log([].slice.call(arguments, 1));
    }
    
    aa("a", "b", "c", "d");
    //['b', 'c', 'd']
  • 取陣列最大最小值
    var arr = [5, 2, 8, -9];
    //原本要處理成 Math.max(5, 2, 8, -9),剛好可用 apply 用陣列傳遞參數的特性。
    //現在也可以使用 ...展開運算子(Spread syntax),直接寫成 Math.max(...arr)。
    //Math.max.apply(null, arr),第一個物件參數沒用到,隨意傳個東西,
    //第一個物件參數傳null、undefined,在非嚴格模式(non-strict),會被置換成global object(在瀏覽器即為window物件)
    console.log(Math.max.apply(null, arr));
    //8



參考:

Linux 用 less 指令儲存檔案

查看內容時,使用「|」指令:
| <m> shell-command
              <m>  represents  any  mark letter.  Pipes a section of the input file to the given shell command.
              The section of the file to be piped is between the first line on the current screen and the posi‐
              tion  marked  by the letter.  <m> may also be ^ or $ to indicate beginning or end of file respec‐
              tively.  If <m> is . or newline, the current screen is piped.
  1. 按「|」,進入 shell-command
  2. 按「^」,表示從頭到目前位置看到的內容;
    按「$」,表示從頭到尾的內容。
  3. 輸入「cat > 要另存的檔案名稱」,按 enter 後即會儲存。


查看內容時,使用「s」指令:
s filename
      Save the input to a file.  This only works if the input is a pipe, not an ordinary file.
這只在查看的內容為 pipe 時,才可用,
例如:
$ cat test.txt | less
打開檔案後,按「s」,再輸入「要另存的檔案名稱」,按 enter 後即會儲存。




參考:

2021年10月6日 星期三

Windows 刪除工作管理員看不到的 Node.js 程序

[狀況]
使用命令列, Node.js 執行 express 監聽 PORT 6150 的程式,
中斷命令列後,Node.js 監聽 PORT 的程序仍在跑。
工作管理員看不到 Node.js 執行的程序,無法經由工作管理員刪除。
但執行 netstat 看的到:
> netstat -anb
 協定   本機位址         外部位址         狀態
 TCP    0.0.0.0:6150     0.0.0.0:0        LISTENING
 [node.exe]


[刪除方式]
方法1:
找出 PID 刪除
> netstat -ano | find "LISTENING" | find "0.0.0.0:6150"
 協定   本機位址         外部位址         狀態         PID
 TCP    0.0.0.0:6150     0.0.0.0:0        LISTENING    21416
刪除 PID 是 21416 的程序
> taskkill /PID 21416
若無法刪除,加 /F 強制刪除
> taskkill /PID 21416 /F


方法2:
到微軟網站下載 Process Explorer
Process Explorer 跟工作管理員類似,但比工作管理員列出更詳盡的資料,
可經由 Process Explorer 進行查找、刪除。



方法3:
如果太多了,且全部要刪除,可直接指定刪除 node.exe 所有程序
> taskkill /IM node.exe /F
成功: 處理程序 "node.exe" (PID 20140) 已經終止了。
成功: 處理程序 "node.exe" (PID 6200) 已經終止了。
成功: 處理程序 "node.exe" (PID 20868) 已經終止了。
成功: 處理程序 "node.exe" (PID 25924) 已經終止了。
成功: 處理程序 "node.exe" (PID 19940) 已經終止了。




參考:


2021年9月20日 星期一

Windows 上 Python 多版本管理(Python Launcher for Windows)

Python 3.x 語法常與 Python 2.x 不相容,
所以Python的windows安裝檔,從3.3開始多了Python launcher可安裝,
Python launcher 可方便選擇使用哪個版本的Python來執行。

安裝時有勾選安裝「py launcher」即會安裝Python launcher,
安裝後可於命令列操作。



[操作]
查看 Python launcher 指令說明
>py -h
Python Launcher for Windows Version 3.9.6150.1013

usage:
py [launcher-args] [python-args] [script [script-args]]
.....

列出安裝的所有Python版本,有「*」星號的是預設版本
>py -0
Installed Pythons found by py Launcher for Windows
 -3.9-64 *
 -3.9-32
 -2.7-64

列出各版本Python安裝的路徑
>py -0p
Installed Pythons found by py Launcher for Windows
 -3.9-64        C:\Program Files\Python39\python.exe *
 -3.9-32        C:\Users\user\AppData\Local\Programs\Python\Python39-32\python.exe
 -2.7-64        C:\Users\user\.windows-build-tools\python27\python.exe

執行預設版本
>py
Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 

執行指定版本
>py -2
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 

執行指定版本,且為32-bit的版本
>py -3-32
Python 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:05:41) [MSC v.1929 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 

使用 2.7 版執行script
>py -2.7 test.py

為不同版本的 Python 安裝套件(package)
>py -3.9 -m pip install 套件名稱

版本查看
>py --version
Python 3.9.6

>py -V
Python 3.9.6

>py -3 -V
Python 3.9.6

>py -3.9 -V
Python 3.9.6



參考:


Python 出現 ImportError: No module named PIL 錯誤

Python 出現 ImportError: No module named PIL 錯誤
原因:程式中有使用 Pillow 影像處理套件(from PIL import Image),但系統沒有安裝 Pillow 套件
解決:安裝 Pillow 套件
> pip install Pillow


參考:


其他:安裝 pip 套件管理工具
下載 https://bootstrap.pypa.io/get-pip.py
>py get-pip.py