JavaScript 学习笔记 3️⃣ 函数
1. 函数对象
- 函数是对象
- 函数原型链: 函数对象 ➡️
Function.prototype
➡️Object.prototype
- 每个函数对象都有3个隐藏属性:上下文、函数代码、
prototype
。 prototype
是一个拥有constructor
属性且值即为函数本身的对象。- 函数作为对象的特性: 可以被保存在变量、对象、数组中,可以作为函数参数、可以返回一个函数,可以拥有方法。
2. 函数字面量
- 用函数字面量创建函数:
var add = function (a,b ){ return a + b; }
- 这是一个匿名函数,add 不是函数名而是保存函数的变量。
- 通过函数字面量创建的函数对象包含一个外部上下文的连接(闭包)。
3. 函数调用
- 除了声明的参数,每个函数还接收两个附加参数:
this
和arguments
。 - 4 种调用模式:方法调用、函数调用、构造器调用、apply调用。
3.1. 方法调用模式
- 当函数被保存为对象的一个属性时,我们称其为一个方法。
this
被绑定到该对象,且该绑定发生于调用时。
3.2. 函数调用模式
- 当函数不是一个对象的属性被调用时,我们称其为一个函数调用。
this
被绑定到全局对象,这是一个设计缺陷,此时不能利用内部函数与当前函数协同工作。
3.3. 构造器调用模式
- JavaScript 是基于原型继承的语言,而非基于类的语言。但它提供了一套和基于类的语言类似的对象构造语法。
- 使用
new
来调用一个函数,会创建一个连接到此函数prototype
成员的新对象,this
会被绑定到新对象上。 - 创建时就为了结合
new
使用的函数称为构造器函数,通常约定将其保存在大写格式命名的变量里。
3.4.Apply
- 函数是对象,所有函数有方法。
apply
接收两个参数,第一个是要绑定到this
的值,第二个是要传递给调用函数的参数数组。var sum = add.apply(null, [3,4])
sum 值为7
4. arguments参数
- 每个函数都有的内置参数
- 通过
arugments
数组参数可以获得函数调用时所有的参数,包括形参定义之外的参数。 - 可以以此写出无固定参数个数的函数。
- 设计缺陷:
arugments
不是一个真的数值,而是一个类似数组的对象,有length属性。
5. 返回值
- 无指定返回值,函数返回
undefined
. - 如果用
new
调用函数,且函数不返回对象,则返回this
(new
“创建”的对象)。
6. 异常
throw
抛出一个exception
对象,其包含name
属性(异常类型)和message
属性(异常描述)。throw{ name: 'TypeError', message: 'this is a type error' }
7. 给函数增加其它方法
- 给
Object.prototype
添加方法,可以使这个方法对所有对象都可用。 - 给
Function.prototype
增加方法,可以使这个方法对所有函数都可用。 - 不用每次输入
.prototype
:Function.prototype.method = function (name, func){ this.prototype[name] = func; return this; };
8.递归
- JavaScript 没有尾递归优化。
9.作用域
- JavaScript 不支持块级作用域。
- JavaScript 支持函数作用域。
10.闭包
- 由于内部函数可以访问它被创建时所处的上下文环境,当内部函数比外部函数有更长的生命周期时,如果内部函数有需要,外部函数的变量会持续保留。
- 简单的例子:
即使var quo = function (status) { return { get_status: function () { return status; } }; }
quo
已经返回,get_status
方法仍然可以访问quo
对象的status
属性。 - 无须复制,内部函数就能访问外部函数的实际变量。(避免在循环中创建函数)。
11.模块
- 通过函数和闭包来构造模块,以完全摒弃对全局变量的使用。
- 一般实现:1️⃣有一个定义了私有变量和函数的函数;2️⃣利用闭包创建可以访问私有变量和函数的内部函数;3️⃣返回这个内部函数,或者把它保存到一个可访问到的地方。
- 例子:
String.method('abc', function(){ var entity = {...}; // 不是全局变量,且只被求值一次 return function(){ return this.replace(/regex/g, function (a,b){ var r = entity[b]; return typeof r=== 'string' ? r : a; } ); }; } () );
12.链式调用
- 让修改对象状态的函数返回
this
而不是undefined
即可实现链式调用。
13. 柯里化(局部套用)
14. 记忆
略