JS的函數(shù)總結(jié)

  • 函數(shù)在javascript里面是對(duì)象。每個(gè)函數(shù)在創(chuàng)建時(shí)會(huì)附加兩個(gè)屬性:函數(shù)的上下文和實(shí)現(xiàn)函數(shù)行為的代碼。
  • 每個(gè)函數(shù)在創(chuàng)建的時(shí)候會(huì)有一個(gè)prototype屬性,它的值是一個(gè)擁有constructor屬性且值為該函數(shù)的對(duì)象。
  • 函數(shù)是對(duì)象,可以像值一樣被使用。函數(shù)可以保存在變量、對(duì)象和數(shù)組中。函數(shù)可以當(dāng)做參數(shù)傳遞給其他函數(shù),函數(shù)也可以返回函數(shù)。因?yàn)楹瘮?shù)是對(duì)象所以函數(shù)也可以擁有方法。
  • 函數(shù)的不同之處在于它可以被調(diào)用。

函數(shù)字面量

  1. 保留字 function
  2. 函數(shù)名,可以被省略。函數(shù)可以利用名字來遞歸調(diào)用自己。如果沒有名字,則稱之為匿名函數(shù)。
  3. 參數(shù)。
  4. 函數(shù)體,在函數(shù)被調(diào)用的時(shí)候執(zhí)行。
    函數(shù)可以被定義在其他函數(shù)中,同事它就能訪問把它嵌套在中的父函數(shù)的屬性。通過函數(shù)字面量創(chuàng)建的函數(shù)對(duì)象包含一個(gè)鏈接到外部的上下文。這被稱之為閉包。

調(diào)用

  • 調(diào)用一個(gè)函數(shù)時(shí),會(huì)暫停當(dāng)前函數(shù)的執(zhí)行,傳遞控制權(quán)和參數(shù)給當(dāng)前函數(shù)。
  • 除了傳遞的參數(shù)之外,每個(gè)函數(shù)還接受兩個(gè)附加的參數(shù):this和 arguments。
  • this的值取決于調(diào)用的模式。在js中有四種調(diào)用模式:
  1. 方法調(diào)用模式
    當(dāng)一個(gè)函數(shù)被保存為一個(gè)對(duì)象屬性時(shí),我們稱之為方法。當(dāng)一個(gè)方法被調(diào)用時(shí),this被綁定到該對(duì)象。如果表達(dá)式包含一個(gè) . 的動(dòng)作,那么它就是被當(dāng)做一個(gè)方法來調(diào)用,方法調(diào)用模式的this指向?qū)ο蟆?/li>
var myObject = {
  value: 0,
  increment: function (inc) {
    this.value += typeof inc === 'number' ? inc : 1;
  }
};
myObject.increment(1);
document.wirteln(myObject.value);
myObject.increment(2);
document.wirteln(myObject.value);
  1. 函數(shù)調(diào)用模式
    當(dāng)一個(gè)函數(shù)并非一個(gè)對(duì)象屬性時(shí),那么它就是被當(dāng)做函數(shù)調(diào)用。
var sum = add(3, 4);

這時(shí),this被綁定到全局對(duì)象上。如果語言設(shè)計(jì)正確,那么 當(dāng)內(nèi)部函數(shù)被調(diào)用時(shí),this 應(yīng)該任然綁定到外部函數(shù)的this變量。
但是

function a(){
  var b = function() {
     console.info(1231231, this);
  }
  b();
}
 a();// 輸出windows this 被綁定到外部去了
// 解決方法
var myObject = {};
myObject.fn = function(){
  var that = this;
  var helper = function () {
    that.value = add(that.value, this.value);
  }
  helper();
}
//解決方法2 箭頭函數(shù)的this指向 外部函數(shù)的this
var myObject = {};
myObject.fn = function() {
  var b = () =>{
     console.info(1231231, this);
  }
  b();
}
  1. 構(gòu)造器調(diào)用模式
    構(gòu)造器調(diào)用模式this將會(huì)指向new出來的對(duì)象。
var Quo = function (string){
  this.status = string;
}

Quo.prototype.get_status = function () {
  return this.status;
}

var myQuo = new Quo("confused");

document.writeln(myQuo.get_status());
  1. apply調(diào)用模式(還有call調(diào)用模式)
    構(gòu)造一個(gè)參數(shù)數(shù)組傳遞給調(diào)用的函數(shù),允許我們選擇this的值。apply接受兩個(gè)值 一個(gè)是this,另外一個(gè)是參數(shù)數(shù)組。
    這些模式在初始化關(guān)鍵參數(shù)this上存在差異。

參數(shù)

當(dāng)函數(shù)被調(diào)用時(shí),會(huì)有一個(gè)arguments數(shù)組??梢跃帉懸粋€(gè)無需指定參數(shù)個(gè)數(shù)的函數(shù)。

var sum = function (){
  var i, sum = 0;
  for (i = 0; i < arguments.length; i += 1) {
    sum += arguments[i];
  }
  return sum;
}

arguments并不是一個(gè)數(shù)組 只是一個(gè)類似數(shù)組的對(duì)象。只有l(wèi)ength屬性,沒有其他數(shù)組方法。

返回

一個(gè)函數(shù)總會(huì)有一個(gè)返回值,如果沒有那么返回undefined。
如果調(diào)用時(shí)加了new,且返回值不是對(duì)象那么返回新對(duì)象即this。

異常

var add = function (a, b) {
  if (typeof a !== 'number' || typeof b !== 'number' ) {
    throw{
      name: 'TypeError',
      message: 'add needs number'
    };
  }

  return a + b;
}

var try_it = function () {
  try {
    add("seven");
  } catch(e) {
    document.writeln(e.name + ':' + e.message);
  }
}

擴(kuò)充類型的功能

Function.prototype.method = function(name, func){
  this.prototype[name] = func;
  return this;
}

Number.method('integer', function(){
  return Math[this < 0? 'ceil' : 'floor'](this);
})

document.writeln((-10/3).integer());

String.method('trim', function () {
  return this.replace(/^\s+|\s+$/g, '');
})
document.writeln('"' + "  neat  ".trim() + '"');

符合條件時(shí)才添加方法

Function.prototype.method = function (name, func) {
  if (!this.prototype[name]) {
    this.prototype[name] = func;
  }
  return this;
}

遞歸 todo

作用域

var foo = function () {
  var a = 3, b = 5;

  var bar = function () {
    var b = 7, c = 11;
    a += b + c;
  };
  //a為3 b 為5
  bar();
  //a為21 b 為5
}

了解js奇怪的作用域。

閉包

函數(shù)可以訪問它被創(chuàng)建時(shí)所處的上下文環(huán)境。這杯稱之為閉包。

var fade = function(node) {
  var level = 1;
  var step = function () {
    var hex = level.toString(16);
    node.style.backgroundColor = '#FFFF' + hex + hex;
    console.info('#FFFF' + hex + hex);
    if(level < 15){
      level += 1;
      setTimeout(step, 1000);
    }
  }
  setTimeout(step, 1000);
}

fade(document.body);

只要step還需要父函數(shù)里的變量那么這個(gè)變量就不會(huì)釋放。

回調(diào)

模塊

我們可以使用函數(shù)和閉包來構(gòu)造模塊,模塊是一個(gè)提供接口卻隱藏狀態(tài)與實(shí)現(xiàn)的函數(shù)或?qū)ο?。通過函數(shù)產(chǎn)生模塊,我們可以摒棄全局變量的使用,從而緩解js的糟糕特性。
定義一個(gè)方法替換尋找字符串中的HTML實(shí)體并把他們替換為對(duì)應(yīng)的字符。

String.method('deentityify', function() {

//需要替換的字符實(shí)體保存在全局變量里太污染,保留在函數(shù)里每次需要求值,但是保留在閉包里很理想
  var entity = {
    quot: '"',
    lt: '<',
    gt: '>'
  };

  return function() {
    return this.replace(/&([^&;]+);/g,
      function (a, b) {
        var r = entity[b];
        return typeof r === 'string' ? r : a;
      }
  }
})

模塊的一般形式就是利用閉包創(chuàng)建可以訪問的私有變量和函數(shù)的特權(quán)函數(shù),最后返回這個(gè)特權(quán)函數(shù),或者把他們保存到一個(gè)可以訪問到的地方。
使用模塊摒棄了全局變量的使用。它促進(jìn)了信息隱藏和其他優(yōu)秀的設(shè)計(jì)實(shí)踐。對(duì)于應(yīng)用的封裝或者構(gòu)建其他單例對(duì)象,模塊模式非常有效。
模塊也可以產(chǎn)生安全的對(duì)象,假定我們要構(gòu)造一個(gè)用來生產(chǎn)序列的對(duì)象。

var serial_maker = function () {
  var prefix = '';
  var seq = 0;
  return {
    set_prefix: function (p) {
      prefix = String(p);
    },
    set_seq: function (s) {
      seq = s;
    },
    gensym: function () {
      var result = prefix + seq;
      seq += 1;
      return result;
    }
  };
};

var seqer = serial_maker();
seqer.set_prefix('Q');
seqer.set_seq(1000);
var unique = seqer.gensym();

級(jí)聯(lián)

一些方法沒有返回值,一些這只或修改對(duì)象的某個(gè)狀態(tài)卻不返回任何值得方法就是經(jīng)典的例子。如果我們讓這些方法返回this而不是undefinded那么就可以啟動(dòng)級(jí)聯(lián)。


getElement('myBoxDiv')
  .move(350, 150)
  .width(100)
  .height(100)
  .color('red')

柯里化

函數(shù)也是值,從而我們可以利用有趣的方式操作函數(shù)值??吕锘试S我們把函數(shù)與傳遞給它的參數(shù)相結(jié)合,產(chǎn)生出一個(gè)新的函數(shù)。

Function.method('curry', function() {
  var slice = Array.prototype.slice,
  args = slice.apply(arguments),
  that = this;
  return function () {
    return that.apply(null, args.concat(slice.apply(arguments)));
  }
})

記憶 todo

函數(shù)可以將先前操作的結(jié)果記錄在某個(gè)對(duì)象里,從而避免無所謂的重復(fù)運(yùn)算。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,667評(píng)論 0 4
  • 函數(shù)和對(duì)象 1、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門語言來說都是核心的概念。通過函數(shù)可以封裝任意多條語句,而且...
    道無虛閱讀 4,927評(píng)論 0 5
  • 一切都要有一個(gè)新的開始了,有一些人就要離開我們的生活,或許這一次分別是另一種意義上的永別。 當(dāng)然有些人的離開輕如鴻...
    鹿哈鹿哈閱讀 413評(píng)論 0 0
  • 今天凌晨下載的軟件,正在試用。
    太空村閱讀 158評(píng)論 0 0
  • 非定常的部分有點(diǎn)難寫我可以看到壓力面高低壓區(qū)域的交替但是這個(gè)交替是怎么來的?
    中場(chǎng)休息室閱讀 86評(píng)論 0 0

友情鏈接更多精彩內(nèi)容