天天看點

Python學習筆記:5.2.3 javascript函數

本文是學習陸老師的《python全棧工程師 - web開發前端基礎》課程的筆記,歡迎學習交流。同時感謝陸老師的精彩傳授!

一、課程目标

  • 函數基本定義
  • 作用域
  • 嵌套函數與閉包
  • 高階函數
  • callee與this

二、詳情解讀

2.1.函數基本定義

函數聲明:

function funcName(args1, args2) {

   …

   …

   return…

}

函數調用傳參時可以傳遞不限數量的參數,在函數内部使用arguments對象接受

函數表達式:

funcName = function (args1, args2) {

   …

   …

   return…

}

使用函數聲明與使用函數表達式定義的差別:

函數聲明會在調用之前已經加載好

函數表達式隻有執行到該行代碼時才會定義函數

代碼示例:

// 函數聲明式定義方式			
function myFun(){
	console.log("hello world")
}
//函數調用
myFun()			
		   
// 函數參數
function mySub(a, b){
	console.log("a=>",a ," b=>", b)
	return a-b
}

// // 傳參調用
// // 順序傳參
// mySub(10,2)
// //不支援關鍵字傳參
mySub(b=2, a=10)
           

運作結果:(注意js是不支援關鍵字傳參的,不要被mySub(10, m=2)迷惑)

Python學習筆記:5.2.3 javascript函數

2.1.1.預設參數位置不限制、按照順序傳參

示例代碼:

function myFun(a, c, b=2, d){
	 console.log("a=>", a, " b=>", b, " c=>", c, " d=>", d)
}

a = 10, b = 2
myFun(10)

a = 10, c = 20, b = 2
myFun(10, 20)

a = 10, c = 20, b = 30
myFun(10,20,30)

a = 10, c = 20, b = 30, d = 40
myFun(10,20,30,40)
           

運作結果:

Python學習筆記:5.2.3 javascript函數

2.1.2.參數清單 - arguments,通過傳參順序索引0,1,2,3…取值

代碼示例:

// python中通過 *args來接受未在函數的形參中定義的參數
//參數清單 - arguments,通過傳參順序索引0,1,2,3...取值
function myFun(a,b){
	console.log(a)
	console.log(b)
	console.log(arguments)
	console.log(arguments[0]) //a
	console.log(arguments[0]) //b
}

myFun(1,20)
myFun(1,2,3,4,5,6)

function myStudents(){
	console.log(arguments)
	if (arguments[0]!=undefined){
		console.log("您的名字:",arguments[0] )
	}
	if (arguments[1]!=undefined){
		console.log("您的性别:",arguments[1] )
	}
}

myStudents("luxp")
myStudents("luxp", "男")
           

運作結果:

Python學習筆記:5.2.3 javascript函數
Python學習筆記:5.2.3 javascript函數

2.1.3.匿名函數 - 函數表達式,可以将匿名函數指派給一個變量

使用函數聲明與使用函數表達式定義的差別

函數聲明會在調用之前已經加載好

函數表達式隻有執行到該行代碼時才會定義函數

代碼示例:

my_func = function(){
  console.log(arguments)
}
my_func()

myHello1() // 這句正常執行,因為函數聲明會在調用之前已經加載好
myHello2() // 這句會報錯,因為匿名表達式隻有執行到該行代碼時才會定義函數

function myHello1(){
	console.log("hello")
}

myHello2 = function(){
	console.log("hello")
}

// 下面兩句都可以正常執行
myHello1()
myHello2() 
           

運作結果:

Python學習筆記:5.2.3 javascript函數

2.1.4.不支援重載:javascript定義多個同名的函數,隻有最後一個生效

示例代碼:

function myfun(a){
	console.log("1")
}
function myfun(a,b){
	console.log("2")
}
function myfun(a,b,c){
	console.log("3")
}
           

運作結果:

Python學習筆記:5.2.3 javascript函數
2.2.作用域

1.在web浏覽器中,全局環境表示為視窗window對象下

2.所有的全局變量與函數都是window的屬性或者方法

3.關閉浏覽器視窗,就銷毀了所有的全局對象

4.每個函數都擁有自己的執行環境

5.每一個代碼執行時都有自己的作用域鍊,作用鍊前端就是目前執行環境的變量對象,作用域鍊下一個變量對象就是下一個包含的環境,直到全局環境

2.2.1.全局變量 - 目前頁面所在的視窗下的環境window BOM,頁面之間的變量并不能互相通路

示例代碼:

var myName = "luxp"
// console.log(window.name)
function myFun(){
	console.log(myName)
}
// console.log(window.myFun)
           

在浏覽器的目前視窗運作結果:

Python學習筆記:5.2.3 javascript函數

在另一個視窗的運作結果:(因為頁面之間的變量并不能互相通路)

Python學習筆記:5.2.3 javascript函數

2.2.2.函數局部作用域

在函數内部使用var定義的變量為函數内部變量,

如果沒有使用var關鍵字,變量就會聲明為全局變量。

es5規範中并沒有塊級作用域,即諸如if, while的{}部分,es6擁有塊級作用域

示例代碼:

my_sex= "男"
function myFun(){
	var my_name = "luxp" // 此處my_name是局部作用域的變量,外部不能通路;如果沒有用var,則是全局作用域的變量,外部可以通路
	my_age = 18
	console.log(my_name, my_sex)
}
myFun()
console.log(my_name)
           

運作結果:

Python學習筆記:5.2.3 javascript函數

2.2.3.函數作用域鍊

變量作用域查找順序由内而外尋找,當在函數内部定義局部變量時,首先會聲明該變量
var  name = "luxp"
			
function seekName1(){		
	var name = "luxp_2"
	console.log(name) // 輸出 luxp_2
	var name = "luxp_1"
	function subFun(){
		var name = "luxp_3"
		// name = "luxp_4"
		console.log(name)  // 輸出 luxp_3
	}
	subFun()
}

seekName1()
			
//局部變量會被預先聲明			 
function seekName2(){
	console.log(name) // 輸出全局變量中的name,為 luxp
	
	// 如果用var聲明name,則上面的語句列印結果為undefined,是相當于在列印name之前聲明了局部變量name
	// var name = "luxp_2" 
				
	// var name = "luxp_1"
	function subFun(){
		var name = "luxp_2"
		// name = "luxp_4"
		console.log(name) // 輸出局部變量中的name,為luxp_2
	}
	subFun()
} 
seekName2()
           
2.3.嵌套函數與閉包
function funcParent() {
	funcChild() {

	}
	return funcChild()
}
           
函數的局部環境在函數調用完畢後,局部環境就會被銷毀,局部環境的變量也會被銷毀,而閉包的用法可以在父級函數執行後,還可以保留對父級的環境變量的引用

2.3.1. 内嵌函數

示例代碼:

function myFunc(i){
	
	function mySubFun(){
		return i
	}
	return mySubFun()
} 
           

2.3.2.将函數作為值傳回

示例代碼:

function create_fun(I){
 	return function (){
 		return "func_"+I
 	}
}
func_array = []
for (i=0;i<5;i++){
   func_array[i]=create_fun(i)
}

           

運作結果:

Python學習筆記:5.2.3 javascript函數

2.3.3.如何讓每個函數輸出不同的值

示例代碼一:

/* 
閉包的原因,所有的函數都會輸出five  
*/

function create_fun(){
	var array = ["one", "two", "three", "four", "five"]
	var func_array = []
	for (i in array){
		console.log(i)
		func_array[i] = function (){
			return array[i]
		}
		
	}
	return func_array
}
//執行這一句的時候,内部函數其實是引用i,而不是i的值,執行
//到最後的時候i的值是5,是以全部的函數的i都是5
func_array = create_fun()
func_array[0]()
           

運作結果:

Python學習筆記:5.2.3 javascript函數
Python學習筆記:5.2.3 javascript函數

示例代碼二:

function create_fun(){
	var array = ["one", "two", "three", "four", "five"]
	var func_array = []
	
	for (i in array){
		func_array[i] = function create_fun(I){
						 //增加了一個内嵌函數
						  return function (){
							   return array[I]
						  }
						//執行,通過執行把i的值固定下來
						}(i)
		
	}
	return func_array
}
func_array = create_fun()
func_array[0]() 
           

運作結果:

Python學習筆記:5.2.3 javascript函數

2.3.4.函數作為參數

函數可以作為一個參數給另一個函數調用,另一個函數就被稱為該函數的高階函數

示例代碼:

function sum(a,b){
	return a+b
}

function sub(a,b){
	return a-b
}

function compute(func, a,b){
	return func(a,b)
}
value = compute(sum, 10,3)
value = compute(sub, 10, 3)
			
function selectEvenNumber(number){
	if (number % 2 == 0) {
		return number
	} else {
		return 0
	}
}
function selectOddNumber(number){
	if (number % 2 == 1) {
		return number
	} else {
		return 0
	}
}

function map(array, func=selectEvenNumber){
	for ( i in array){
		array[i] = func(array[i])
	} 
} 

array = [1,2,3,4,5,6,7,8,9]
map(array)
console.log(array)

array = [1,2,3,4,5,6,7,8,9]
map(array, selectOddNumber)
console.log(array)

/* 
js中常見的一種高階用法 
 */

function myfun(args, func){}
myfunc(args, function(){})
           

運作結果:

Python學習筆記:5.2.3 javascript函數
Python學習筆記:5.2.3 javascript函數
2.4.高階函數

2.4.1.函數作為值

function func1(){}
function func2(func){
	return func()
}

return func2(func1)
           
2.5.callee與this

2.5.1.arguments.callee

arguments.callee可以在内部對函數名實作解耦

callee代表這對函數自身的引用

可以降低函數名與内部調用的耦合性

示例代碼一:

function myFun(){
	console.log(arguments)
	console.log(arguments.callee)
}
           

運作結果:

Python學習筆記:5.2.3 javascript函數

示例代碼二:

/*利用遞歸計算階乘 */

// 這種方法,當函數名改變時,函數内部的遞歸方法名也得修改
function jiecheng(num) {
	if (num === 1) {
		return 1
	} else {
		return num * jiecheng(num-1)
	}
}

// 這種方法不一樣,無論函數名如何改變,函數内部的遞歸方法名不用修改
function jiecheng(num) {
	if (num === 1) {
		return 1
	} else {
		return num * arguments.callee(num-1)
	}
} 

           

2.5.2.this

在函數内部,this引用了函數的執行環境
/* this 指向對象由所在的執行環境決定 */

console.log(this)

function myFun(){
	console.log(this)
	// return this
	this.nickname = "luxp"
}

function myFun(){
	function mySubFun(){
		console.debug(this)
		return this
	}
	return mySubFun()
}

function myFun(){
	var o = new Object()
	o.func = function(){
		console.log(this)
	}
	return o
}

           

運作結果:

Python學習筆記:5.2.3 javascript函數

三、課程小結

  • 1.函數基本定義
  • 2.作用域
  • 3.嵌套函數與閉包
  • 4.callee與this

繼續閱讀