4.函数是特殊的对象 - JS

万物皆是对象,一切存为数据/值。对象是值,函数也是值。

行为对象 - 函数

函数是可以被调用的“行为/动作对象”,一个函数就是一个行为/动作。作为对象的基本操作都适用,如增/删属性,按引用传递等。


属性 name

  1. name 属性就是函数名;
  2. 匿名函数(包括箭头函数)本身没有函数名,name='',但可以通过赋值给变量,使变量成为函数,此时函数名就是变量名了;
  3. 如果将非匿名函数赋值给变量,则函数名函数声明时的名称;
  4. Function 构造函数返回的函数,name 属性的值为 anonymous
  5. bind 返回的函数,name 属性值会加上 bound 前缀;
  6. 对象里的方法,也有 name 属性·。
function func() {}
func.name			// 'func'

let func2 = function () {}
func2.name			// 'func2'

let g = function func3() {}
g.name				// 'func3' !!

(new Function).name	// anonymous

func.bind({}).name // "bound func"

const o = { sayHi() {} }
o.sayHi.name		// 'sayHi'

属性 length

函数的 length 属性反映参数数量,计算原则:

  1. 一个普通参数的贡献是 1;
  2. 一个解构参数的贡献是 1;
  3. 剩余参数的贡献是 0;
  4. 默认参数的贡献是0,且截断其后的参数贡献。
(function (a) {}).length			// 1
(function ([a, b]) {}).length		// 1
(function ({ a, b }) {}).length 	// 1
(function (a, ...rest) {}).length	// 1
(function (a, b=0) {}).length		// 1
(function (a=0, b) {}).length		// 0 默认参数后的贡献被截断

自定义属性

作为一个对象,函数可以自定义任何属性,并且可以在函数体中使用。

函数属性有时会用来替代闭包。闭包的环境更隐蔽,而函数的属性可以更直观的访问。

function sayHi() { console.log(`${++sayHi.callCount} 次说你好。`) }
sayHi.callCount = 0;
sayHi()		// 第 1 次说你好。
sayHi()		// 第 2 次说你好。

/* 使用函数属性建立计数器,而不是闭包:
	闭包需要在外部函数中声明计算值的变量,函数属性直接绑定在函数上。 */
function makeCounter(init=0) {
	// let val = init;
  	function counter() {
  		// return val++;
  		return counter.val++;
  	}
  	counter.val = init;	// 属性初始化
  	return counter;
}
let counter = makeCounter();
counter();	 			// 0
counter(); 				// 1

函数的构造函数 Function

任何对象都有构造函数,函数作为一个对象也不例外,但函数对象的构造函数却很少使用,是不得已才使用的创建函数的方法。

基本语法 let func = new Function ([arg1, arg2, ...argN], functionBody)

  1. 参数都是字符串,最后一个参数是函数体字符串;
  2. 通过执行字符串来构建函数,会遇到和 eval() 类似的的安全问题和(相对较小的)性能问题,不同的是,Function 构造函数创建的函数只能在全局作用域中运行,所以不能用来创建闭包;
  3. 应用场景特殊,比如在复杂的 Web 应用程序中,当需要从服务器获取代码、动态地从模板编译函数时才会使用。
let x = 10;		// 一个全局变量

function gen1() {
  	let x = 20;
  	return new Function("return x;"); // 这个 x 指向全局 x,不能构成闭包
}

function gen2() {
  	let x = 20;
  	function f() { return x; } 	// 这个 x 指向上面的局部 x
	return f;		// 此函数与内部环境构成闭包!!
}

const f1 = gen1();
f1()			// 10
const f2 = gen2();
f2()			// 20

你可能感兴趣的:(#,JS,函数进阶,javascript,前端,开发语言,ecmascript,学习,笔记)