JS的函数总结

  • 函数在javascript里面是对象。每个函数在创建时会附加两个属性:函数的上下文和实现函数行为的代码。
  • 每个函数在创建的时候会有一个prototype属性,它的值是一个拥有constructor属性且值为该函数的对象。
  • 函数是对象,可以像值一样被使用。函数可以保存在变量、对象和数组中。函数可以当做参数传递给其他函数,函数也可以返回函数。因为函数是对象所以函数也可以拥有方法。
  • 函数的不同之处在于它可以被调用。

函数字面量

  1. 保留字 function
  2. 函数名,可以被省略。函数可以利用名字来递归调用自己。如果没有名字,则称之为匿名函数。
  3. 参数。
  4. 函数体,在函数被调用的时候执行。
    函数可以被定义在其他函数中,同事它就能访问把它嵌套在中的父函数的属性。通过函数字面量创建的函数对象包含一个链接到外部的上下文。这被称之为闭包。

调用

  • 调用一个函数时,会暂停当前函数的执行,传递控制权和参数给当前函数。
  • 除了传递的参数之外,每个函数还接受两个附加的参数:this和 arguments。
  • this的值取决于调用的模式。在js中有四种调用模式:
  1. 方法调用模式
    当一个函数被保存为一个对象属性时,我们称之为方法。当一个方法被调用时,this被绑定到该对象。如果表达式包含一个 . 的动作,那么它就是被当做一个方法来调用,方法调用模式的this指向对象。
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. 函数调用模式
    当一个函数并非一个对象属性时,那么它就是被当做函数调用。
var sum = add(3, 4);

这时,this被绑定到全局对象上。如果语言设计正确,那么 当内部函数被调用时,this 应该任然绑定到外部函数的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 箭头函数的this指向 外部函数的this
var myObject = {};
myObject.fn = function() {
  var b = () =>{
     console.info(1231231, this);
  }
  b();
}
  1. 构造器调用模式
    构造器调用模式this将会指向new出来的对象。
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调用模式(还有call调用模式)
    构造一个参数数组传递给调用的函数,允许我们选择this的值。apply接受两个值 一个是this,另外一个是参数数组。
    这些模式在初始化关键参数this上存在差异。

参数

当函数被调用时,会有一个arguments数组。可以编写一个无需指定参数个数的函数。

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

arguments并不是一个数组 只是一个类似数组的对象。只有length属性,没有其他数组方法。

返回

一个函数总会有一个返回值,如果没有那么返回undefined。
如果调用时加了new,且返回值不是对象那么返回新对象即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);
  }
}

扩充类型的功能

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() + '"');

符合条件时才添加方法

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奇怪的作用域。

闭包

函数可以访问它被创建时所处的上下文环境。这杯称之为闭包。

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还需要父函数里的变量那么这个变量就不会释放。

回调

模块

我们可以使用函数和闭包来构造模块,模块是一个提供接口却隐藏状态与实现的函数或对象。通过函数产生模块,我们可以摒弃全局变量的使用,从而缓解js的糟糕特性。
定义一个方法替换寻找字符串中的HTML实体并把他们替换为对应的字符。

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

//需要替换的字符实体保存在全局变量里太污染,保留在函数里每次需要求值,但是保留在闭包里很理想
  var entity = {
    quot: '"',
    lt: '<',
    gt: '>'
  };

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

模块的一般形式就是利用闭包创建可以访问的私有变量和函数的特权函数,最后返回这个特权函数,或者把他们保存到一个可以访问到的地方。
使用模块摒弃了全局变量的使用。它促进了信息隐藏和其他优秀的设计实践。对于应用的封装或者构建其他单例对象,模块模式非常有效。
模块也可以产生安全的对象,假定我们要构造一个用来生产序列的对象。

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();

级联

一些方法没有返回值,一些这只或修改对象的某个状态却不返回任何值得方法就是经典的例子。如果我们让这些方法返回this而不是undefinded那么就可以启动级联。


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

柯里化

函数也是值,从而我们可以利用有趣的方式操作函数值。柯里化允许我们把函数与传递给它的参数相结合,产生出一个新的函数。

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

函数可以将先前操作的结果记录在某个对象里,从而避免无所谓的重复运算。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容

  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,231评论 0 4
  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,551评论 0 5
  • 一切都要有一个新的开始了,有一些人就要离开我们的生活,或许这一次分别是另一种意义上的永别。 当然有些人的离开轻如鸿...
    鹿哈鹿哈阅读 336评论 0 0
  • 今天凌晨下载的软件,正在试用。
    太空村阅读 139评论 0 0
  • 非定常的部分有点难写我可以看到压力面高低压区域的交替但是这个交替是怎么来的?
    中场休息室阅读 59评论 0 0