国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JavaScript函數、閉包、原型、面向對象學習筆記

2019-11-19 13:01:10
字體:
來源:轉載
供稿:網友

斷言

單元測試框架的核心是斷言方法,通常叫assert()。

該方法通常接收一個值--需要斷言的值,以及一個表示該斷言目的的描述。

如果該值執行的結果為true,斷言就會通過;

否則,斷言就會被認為是失敗的。

通常用一個相應的通過(pass)/ 失敗(fail)標記記錄相關的信息;

function assert(value, desc) {  let li = document.createElement('li');  li.className = value ? 'pass' : 'fail';  li.appendChild(document.createTextNode(desc));  document.getElementById('results').appendChild(li);}// 斷言函數function assert(value, desc) {  if (value) {    console.log(`/033[32m ${desc} /033[0m`);  // 斷言通過 綠色字體  } else {    console.log(`/033[31m ${desc} /033[0m`);  // 斷言失敗 紅色字體  }}

函數

  • JavaScript是一門函數式語言
  • 在JavaScript中,函數是第一型對象。函數可以共處,可以視作為其他任意類型的對象。就像普通的JavaScript數據類型,,函數可以被任意變量進行引用,或聲明成對象字面量,甚至可以將其作為函數參數進行傳遞。
  • 函數是第一型對象
  • 可以通過字面量進行創建。
  • 可以賦值給變量、數組或其他對象的屬性。
  • 可以作為參數傳遞給函數。
  • 可以作為函數的返回值進行返回。
  • 可以擁有動態創建并賦值的屬性。
  • 命名一個函數時,該名稱在整個函數聲明范圍內是有效的。如果函數聲明在頂層,window對象上的同名屬性則會引用到該函數。
  • 所有的函數都有一個name屬性,該屬性保存的是該函數名稱的字符串。匿名函數的name屬性值為空。
  • 在JavaScript中,作用域是由function進行聲明的,而不是代碼塊。聲明的作用域創建于代碼塊,但不是終結于代碼塊(其他語言是終結于代碼塊的)
if (window) {  var x = 123;}alert(x);

執行代碼后,會彈出123,是因為JavaScript在大括號關閉處并沒有終止其作用域。

  • 變量聲明的作用域開始于聲明的地方,結束于函數的結尾,與代碼嵌套無關。
  • 命名函數的作用域是指聲明該函數的整個函數范圍,與代碼嵌套無關;
  • 對于作用域聲明,全局上下文就像一個包含頁面所有代碼的超大型函數。
  • 所有的函數調用都會傳遞兩個隱式參數:argument和this

作為函數進行調用

如果一個數不是作為方法、構造器、或者通過apply()或call()進行調用的,則認為它是“作為函數”進行調用的。

function ninja() {};ninja()var samurai = function() {};samurai()
  • 以這種方式調用時,函數的上下文是全局上下文---window對象。

作為方法進行調用

當一個函數被賦值給對象的一個屬性,并使用引用該函數的這個屬性進行調用時,那么函數就是作為該對象的一個方法進行調用的。

var 0 = {};o.whatever = function() {};o.whatever();
  • 將函數作為對象的一個方法進行調用時,該對象就變成了函數上下文,并且在函數內部可以以this參數的形式進行訪問。

作為構造器進行調用

  • 將函數作為構造器進行調用,需要在函數調用前使用new關鍵字

創建一個新的空對象;

傳遞給構造器都對象是this參數,從而成為構造器的函數上下文;

如果沒有顯式都返回值,新創建的對象則作為構造器的返回值進行返回。

function Ninja() {  this.skulk = function() { return this; }}var ninja1 = new Ninja();var ninja2 = new Ninja();

構造器的目的是通過函數調用初始化創建新的對象。

函數調用方式差異

  • 函數調用方式之間點主要差異是:作為this參數傳遞給執行函數的上下文對象之間點區別。

作為方法調用,該上下文是方法的擁有者;
作為全局函數進行調用,其上下文永遠是window(也就說,該函數是window的一個方法)。
作為構造器進行調用,其上下文對象則是新創建的對象實例。

使用apply()和call()方法

  • 通過函數的apply()方法來調用函數,需要給apply()傳入兩個參數:一個是函數上下文的對象,另一個是作為函數參數所組成的數組;
  • 通過函數的call()方法來調用函數,需要給call()傳入兩個參數:一個是函數上下文的對象,另一個是作為函數參數的參數列表,而不是單個數組;
function juggle() {  var result = 0;  for (var n = 0; n < arguments.length; n++) {    result += arguments[n]  }  this.result = result;}var ninja1 = {};var ninja2 = {};juggle.apply(ninja1, [1,2,3,4]);juggle.call(ninja2, 5,6,7,8)assert(ninja1.result === 10, 'juggled via apply');assert(ninja2.result === 26, 'juggled via call');

使用apply()和call()可以選擇任意對象作為函數上下文;

函數總結

函數是第一型對象;

  • 通過字面量進行創建。
  • 賦值給變量或屬性。
  • 作為參數進行傳遞。
  • 作為函數結果進行返回。
  • 擁有屬性和方法。

函數是通過字面量進行創建的,其名稱是可選的。

在頁面生命周期內,瀏覽器可以將函數作為各種類型的事件處理程序進行調用。

變量的作用域開始于聲明處,結束于函數尾部,其會跨域邊界(如:大括號)

內部函數在當前函數的任何地方都可用(提升),即便是提前引用。

函數的形參列表和實際參數列表的長度可以是不同的。

  • 未賦值的參數被設置為undefined。
  • 多出的參數是不會綁定到參數名稱的。

每個函數調用都會傳入兩個隱式參數。

  • arguments,實際傳入的參數集合。
  • this,作為函數上下文的對象引用。

可以用不同的方法進行函數調用,不同的調用機制決定了函數上下文的不同。

  • 作為普通函數進行調用時,其上下文是全局對象(window)。
  • 作為方法進行調用時,其上下文是擁有該方法的對象。
  • 作為構造器進行調用時,其上下文是新分配的對象實例。
  • 通過函數的apply()或call()方法進行調用時,上下文可以設置成任意值。

匿名函數

為了不讓不必要的函數名稱污染全局命名空間,可以創建大量的小型函數進行傳遞,而不是創建包含大量命令語句的大型函數。

遞歸

  • 遞歸:當函數調用自身,或調用另外一個函數,但這個函數的調用樹中的某個地方又調用到了自己時,就產生了遞歸。
  • 遞歸的兩個條件:引用自身,并且有終止條件。

閉包

  • 閉包是一個函數在創建時允許自身函數訪問并操作該自身函數之外的變量時所創建的作用域
  • 閉包可以讓函數訪問所有的變量和函數,只要這些變量和函數存在于該函數聲明時的作用域內就行。
var outerValue = 'ninja';var later;function outerFunction() {  // 該變量的作用域限制在該函數內部,并且在函數外部訪問不到;  var innerValue = 'samurai';  // 在外部函數內,聲明一個內部函數。  // 注意:聲明該函數時,innerValue是在作用域內的  function innerFunction() {    assert(outerValue, 'I can see the ninja');    assert(innerValue, 'I can see the samurai');    // 將內部函數引用到later變量上,由于later在全局作用域內,所以可以對它進行調用。    later = innerFunction;  }}// 調用外部函數,將會聲明內部函數,并將內部函數賦值給later變量。outerFunction();// 通過later調用內部函數。// 我們不能直接調用內部函數,因為它的作用域(和innerValue一起)被限制在outerFunction內。later();

閉包使用場景:私有變量

在構造器內隱藏變量,使其在外部作用域不可訪問,但是可以存在于閉包內。

function Ninja() {  var feints = 0;  this.getFenits = function() {    return feints;  }  this.feint = function() {    feints++;  }}var ninja = new Ninja();ninja.feint();assert(ninja.getFenits() === 1, '調用一次,內部變量++');assert(ninja.feints === undefined, '函數外部不可訪問')

變量的作用域依賴于變量所在的閉包

閉包記住的是變量的引用,而不是閉包創建時刻該變量的值

原型與面向對象

  • 所有的函數在初始化時都有一個prototype屬性,該屬性的初始值是一個空對象。
  • 使用new操作符將函數作為構造器進行調用的時候,其上下文被定義為新對象的實例。
  • 在構造器內的綁定操作優先級永遠高于在原型上的綁定操作優先級。因為構造器的this上下文指向的是實例自身,所以我們可以在構造器內對核心內容執行初始化操作。
  • 通過instanceof操作,可以判斷函數是否繼承了其原型鏈中任何對象的功能。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 辽阳县| 吴川市| 昌乐县| 苍南县| 枣庄市| 平度市| 福清市| 墨竹工卡县| 全南县| 筠连县| 大邑县| 泸西县| 武山县| 柳河县| 密云县| 连云港市| 莱阳市| 花莲县| 克拉玛依市| 玉田县| 都安| 华蓥市| 迁安市| 武乡县| 郑州市| 贺州市| 武汉市| 宜良县| 华亭县| 汕尾市| 玉树县| 吴旗县| 梧州市| 宁国市| 承德市| 安阳市| 亳州市| 古田县| 大渡口区| 积石山| 二手房|