摘要:作用域鏈的用途,是為了保證對執行環境有權訪問的所有變量和函數的有序的訪問。即全局作用域和局部作用域的變量的訪問權限是由作用域鏈決定的。搜索過程始終從作用域鏈的前端開始,然后逐級的向后回溯,直到找到標識符如果找不到標識符,通常會報錯。
ECMAScript核心語法結構之函數詳解 一、函數的概念
函數是一段可以反復調用的代碼塊。接受輸入的參數,不同的參數會返回不同的值。
1.函數的定義ECMAScript中是使用function關鍵字來聲明,后面跟一組參數以及函數體。
1) 聲明函數
function sum (num1,num2){ return num1 + num2; } //可以先使用后定義。 解析器在執行環境中加載數據時,會率先讀取函數聲明。
2) 函數表達式:將一個匿名函數賦值給一個變量
var sum = function (num1,num2){ return num1 + num2; } //必須定義后使用(否則會報錯)。到解析器執行到它所在的代碼行,才會真正被解析執行
3) 構造函數(幾乎不用)
var sum = new Funtion( "num1", "num2", "return num1 + num2" ) //等同于上面的聲明函數2.函數的調用(括號運算符)
函數可以通過其函數名調用,后面還要加上一對圓括號和參數(如果有多個參數,用逗號隔開)
function sum(num1, num2) { return num1 + num2; } sum(1, 1) //23.函數的參數
1.什么是參數
函數運行的時候,有時需要提供外部數據,不同的外部數據會得到不同的結果,這種外部數據就叫參數。
function sum (num1,num2){ return num1 + num2; } sum(1,2); //3 sum(1) //NAN num2 undefind;
2.參數的傳遞方式 - 按值傳遞
(1) 基本類型值的傳遞如同基本類型變量的復制一樣。
(2) 引用類型值的傳遞則如同引用類型變量的復制一樣(將這個值在內存中的地址復制給了一個局部變量,因此這個局部變量的變化就會反在函數的外部)
//基本類型的傳遞 function addTen(num) { num += 10; return num; } var count = 20; var result = addTen(count); alert(count); //20,沒有變化 alert(result); //30 //引用類型的傳遞 var person = new Object(); function setName(obj) { alert(person.name); //undefined obj.name = "Nicholas"; alert(person.name) //"Nicholas" } setName(person); alert(person.name); //"Nicholas"
3.arguments對象(讀取函數體內部所有參數)
arguments對象是一個類數組(有length屬性,但沒有數組的任何方法)
可以編寫無需指定參數個數的函數
var sum=function(){ var sum=0; for(var i=0;i4. 函數的返回值(return) 函數可以通過return語句跟要返回的值來實現返回值。函數在執行完return語句之后停止并立即退出。因此,在return語句之后的任何代碼永遠都會回執行。
function sum(num1, num2) { return num1 + num2; alert("Hello world") //永遠不會執行 }return語句不是必須的,如果沒有的話,該函數就不會返回任何值,或者說返undefined;
function sum(num1, num2) { alert (num1 + num2) } //undefined5.函數沒有重載(函數的重復聲明)函數重載:在其他語言(Java)中可以為一個函數體編寫兩個定義,只要定義的簽名(接收的參數的類型和參數不同即可))
在ECMASctipt中如果同一個函數被多次聲明,后面的聲明就會覆蓋前面的聲明。function addSomeNumber(num){ return num + 100; } function addSomeNumber(num) { return num + 200; } var result = addSomeNumber(100); //3006.函數的屬性和方法(1) name屬性(返回name的名字)
function sum (){} sum.name // "sum"(2) length 屬性
函數的length屬性返回函數預期傳入的參數個數,即函數定義之中的參數個數。
function f(a,b){ return f.length } f(1,2,3,4) //2 ==> length屬性就是定義是的參數個數。不管調用時傳入了多少參數,length屬性的始終等于2(3)apply()和call()
每個函數都包含兩個非繼承而來的方法:apply()和和call()。這兩個方法的用途都是在特定的作用域中調用函數,實際上等于設置函數體內this對象的值。
apply()方法接收兩個參數,一個是在其運行函數體內的作用域,另一個是參數數組。其中第二個參數是數組或者arguments對象。
call()方法接收兩個參數,第一個參數是this值沒有變化,變化的是其余參數都是直接傳遞給函數(的參數必須逐個列舉出來)1.傳參
function sum(num,num2){ return num1 + num2; } function callSum(){ return sum.call(this,num1,num2); } alert(callSum(10,10)); //202.擴充函數賴以運行的作用域 (改變this指向的值)
var color = "red"; var o = { color: "blue" } sayColor.call(); //red(默認傳遞參數this) sayColor.call(this); //red sayColor.call(window); //red sayColor.call(o); //blue二、函數的作用域和作用域鏈 1.作用域(1)什么是作用域
作用域(scope)指的是變量存在的范圍。 在es5中的,Javascript只有兩種作用域:一種是全局作用域,變量在整個程序中一直存在,所有地方都可以讀取;另一種是函數作用域,變量只在函數內部存在。(es6中又新增了塊級作用域)
全局作用域可以在代碼的任何地方都能被訪問var color1 = "blue"; function colorFn (){ var color2 = "red"; color3 = "yellow"; console.log(color1); console.log(color2); console.log(color3); } colorFn(); console.log(color1); //"blue" console.log(color2); // error console.log(color3); //"yellow" //函數changeColor()的作用域鏈包含兩個對象:它自己的變量對象(定義著arguments對象)和全局的變量的對象2.作用域鏈1.當代碼在一個執行環境中執行時,就會創建一個作用域鏈。
2.作用域鏈的用途,是為了保證對執行環境有權訪問的所有變量和函數的有序的訪問。即全局作用域和局部作用域的變量的訪問權限是由作用域鏈決定的。
3.作用域鏈的是從當前的執行環境的變量對象在這個環境中可以訪問的變量對象開始,到全局執行環境的變量對象結束。(在這個環境中可以訪問的變量)
4.內部環境可以通過作用域鏈訪問所有外部環境,但是外部環境不能訪問內部環境中的任何變量和函數。
5.標示符(變量、函數、屬性的名字,或者函數的參數)的解析是沿著作用域鏈一級一級的搜索標示符的過程。搜索過程始終從作用域鏈的前端開始,然后逐級的向后回溯,直到找到標識符(如果找不到標識符,通常會報錯)。
//在局部作用域中定義的變量可以在局部環境中與全局變量中互換使用 var color = "blue"; function changeColor(){ var anotherColor = "red"; function swapColors(){ var tempColor = anotherColor; anotherColor = color; color = tempColor; //這里可以訪問color、anotherColor和tempColor } //這里可以訪問color和anotherColor,但不能訪問tempColor swapColors(); } //這個只能訪問color; changeColor();三、函數的其他知識點 1.閉包函數(1) 什么是閉包函數
閉包函數是指有權訪問另一個函數作用域中的變量的函數
(2) 創建閉包的常見方式,就是在一個函數內部創建另一個函數//在函數內部可以讀取函數外部的變量 var localVal = 30; function outer(){ return localVal; } outer();//30 //在函數外部自然無法讀取函數內的局部變量 function outer(){ var localVal = 30; } alert(localVal);//error //通過閉包函數來讀取讀取outer函數內部的變量 function outer(){ var localVal = 30; function inner(){ alert(localVal); } return inner; } var func = outer(); func();//30(3) 閉包的優缺點
1) 使用閉包的好處是不會污染全局環境,方便進行模塊化開發,減少形參個數,延長了形參的生命周期 2) 閉包會把函數中變量的值保存下來,供其他函數使用,這些變量會一直保存在內存當中占用大量的內存,使用不當會造成內存泄漏2.回調函數(1) 什么是回調函數(作為值的函數)
回調函數也被稱作高階函數,是一個被作為參數傳遞給另一個函數的函數。 function someFunction(someNum,callback){ return callback(someNum); } function add10(){ return num + 10; } someFunction()(2) 應用場景實例:
1.數組中的一些方法 sort()、reverse()、forEach()、filter()等 var friends = ["Mike", "Stacy", "Andy", "Rick"]; friends.forEach(function (eachName, index){ console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick }); 2.事件的綁定 //原生綁定事件 document.body.addEventListener("cilck",function(){ alert("body Clicked"); }); //jq $("#btn_1").click(function() { alert("Btn 1 Clicked"); }); 3.ajax的請求 function getAjax (options, callback) { var xhr = new XMLHttpRequest(); xhr.open("get", options.url); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(xhr.status == 200){ callback && callback(xhr.responseText); } } }; xhr.send(); }3.遞歸函數1.什么是遞歸函數
遞歸函數是一個在函數通過名字調用自身的情況下構成的。遞歸函數必須要有邊界條件function factorial(num){ if(num <= 1){ return 1 }else { return num * factorial(num - 1); } }2.arguments.calls()是一個指向正在執行的函數指針 (嚴格模式下不支持)
//當函數名發生改變時會導致代碼出錯var anotherFactorial = factorial; factorial = null; alert(anotherFactorial(4)); //出錯! function factorial(num){ if(num == 1){ return 1; } else { return num * arguments.callee(num-1) } }3.嚴格和非嚴格都有效
var factorial = (function f (num){ if(num == 1){ return 1; } else { return f(num-1) } })4.自執行函數(1)什么是執行函數
立即執行函數,就是在定義的時候立即執行的函數,執行完以后釋放,包括函數內部的所有變量(執行完畢,立即銷毀其作用域鏈)(2)立即執行函數的寫法
1.常用寫法 (function(){ })(); 2.w3c建議方式 (function(){ }()); 3.錯誤寫法 function(){ }();函數聲明后面不能跟花括號(js會把function關鍵字當做一個函數聲明的開始)
函數表達式的后可以跟圓括號。要將函數聲明轉變成函數表達式
除圓括號外,!、+、-、=等運算符,都將函數聲明轉換成函數表達式
!function(){}(); +function(){}(); -function(){}(); var fn=function(){}();(3) 模仿塊級作用域
function outputNumbers (count){ for(var i=0; i3.應用場景
var list = document.getElementsByTagName("li"); for (var i = 0, len = list.length; i < len; i++) { (function(i){ //為了獲得不同的i值,使用立即調用函數 list [i].onmouseover = function() { console.log("index is :" + i); } })(i); }
- 0
- 1
- 3
- 4
參考:
JavaScript高級程序設計(第3版)
https://wangdoc.com/javascrip...
https://www.cnblogs.com/caoru... JavaScript函數之作用域 / 作用鏈域 / 預解析
https://www.cnblogs.com/bucho... JavaScript中作用域和作用域鏈的簡單理解(變量提升)
https://www.cnblogs.com/jingw... 閉包
https://www.cnblogs.com/langq...
https://www.cnblogs.com/mengf...
https://www.cnblogs.com/mafei... 立即執行函數
https://baijiahao.baidu.com/s... 立即執行函數
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/109328.html
摘要:上節我們講了同源策略,這節我們講講如何跨域。當這些從的腳本執行出錯,因為違背了同源策略為了保證用戶信息不被泄露,錯誤信息不會顯示出來,取而代之只會返回一個。 前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS),本著提升技術水平,打牢基礎知識的中心思想,我們開課啦(每...
摘要:前端最基礎的就是。前面我們已經基本掌握常規的語法語義,以及基本的使用方法。等價于當載入就緒執行一個函數回調。返回一組匹配的元素。據提供的原始標記字符串,動態創建由對象包裝的元素。同時設置一系列的屬性事件等。 前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS),本著提...
摘要:前端最基礎的就是。前面我們已經基本掌握常規的語法語義,以及基本的使用方法。等價于當載入就緒執行一個函數回調。返回一組匹配的元素。據提供的原始標記字符串,動態創建由對象包裝的元素。同時設置一系列的屬性事件等。 前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS),本著提...
摘要:同源策略是什么同源策略是瀏覽器的一個安全功能,不同源的數據禁止訪問。或許你可以說驗證,在瀏覽器沒有同源策略的情況下這些都可以繞過去。總結同源策略是蠻好的,防御了大部分的攻擊。 前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS),本著提升技術水平,打牢基礎知識的中心思...
摘要:前端最基礎的就是。幫助從舊的事件方法轉換,和。方法移除用綁定的事件處理程序。特定的事件處理程序可以被移除元素上提供事件名稱,命名空間,處理函數。用于過濾器的觸發事件的選擇器元素的后代。事件觸發模擬觸發原生使用觸發。 前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS)...
閱讀 810·2021-10-14 09:43
閱讀 2133·2021-09-30 09:48
閱讀 3457·2021-09-08 09:45
閱讀 1104·2021-09-02 15:41
閱讀 1900·2021-08-26 14:15
閱讀 787·2021-08-03 14:04
閱讀 2987·2019-08-30 15:56
閱讀 3083·2019-08-30 15:52