JavaScript函数 --入门篇

tech2024-07-26  51

JavaScript函数入门

一:认识JavaScript函数

1.函数是对象

所有JavaScript函数都是对象,所以它具有对象的全部特征:
可以通过字面量创建 function fn() {} 1 可以赋值给变量,数组或其他对象的属性可以作为函数的参数来传递可以作为函数的返回值可以动态创建和分配属性

2.函数作为对象,具有属性:如下案例,用作标记属性、计算结果属性、工具函数属性等

标记属性

可以在函数上挂载一些标记属性,如该函数是否可用、函数序号、使用环境等等与该函数有关的特征信息。

// 例1:函数的封装者标记 function fn(){} fn.useAble = false // 例2:函数集合去重存储 var fnStore = {  nextId: 1,  cache: {},  add: function(fn) {     if (!fn.id) {     fn.id = this.nextId++;     this.cache[fn.id] = fn;     return true;   }  } }; function fn1(){} fnStore.add(fn1) 1234567891011121314151617
计算结果属性

在某函数运行的时间复杂度高或返回值比较密集时,可以用空间换时间,通过在该函数上挂载一个结果集对象的属性的方式,在具体运算前先对该对象进行搜索,有则取值返回,无则运算后得值存储下来并返回,这样可以大大加快运行速度,如下例:

// 例1: function fn(param){ if(fn.results){ fn.results = {} } if(fn.results[param] !== undefined){ return fn.results[param] } else{ const result = ...xxx // 函数具体逻辑 fn.results[param] = result } } 12345678910111213
工具函数属性

在我们经常见到的api当中,很多除核心逻辑外的封装以及语法糖,尤其是对该函数的一些常用的构造方式,都会被封装成一个工具函数,然后作为属性挂载在该封装函数上,如下例:

// 例1:Promise的工具函数resolve、reject、all、race等函数都通过函数属性方式挂载在Promise上,而不是作为实例方法或原型方法挂载在每个实例对象或者原型对象上。 function Promise(excutor){} Promise.resolve = function(value){} // 注意这里不是回调函数参数resolve,而是Promise工具函数resolve,用来快速得到一个resolved状态的Promise。 Promise.reject = function(error){} // 与上同理 Promise.all/race/xxx = function(){} // 例2:axios function axios(){} axios.get = function(url){} // 以及axios.post/delete/put等工具函数都是挂载在axios上 12345678

3.函数作为对象,可以传递:如下案例,回调函数

熟悉Java的人都知道,在Java中,方法并不是一个独立的对象,也没有方法单独的存储方式,所以它不可能作为引用类型或者基本类型传递。但是在JavaScript中函数或者方法传递是可以做到的,因为函数是对象,所以它可以被存储并被传递。

function fn(){ console.log(111) }; setInterval(fn1, 1000) 12

二:定义JavaScript函数

方式1:函数声明语句(通过字面量创建函数)

普通函数
function fn(){} 1
生成器函数
function* myGen(){ yield 1; } 1

有关生成器函数更详细的内容,会在另外一篇博客再做研究,在这里不展开讨论。

方式2:函数表达式(通过表达式创建函数)

const fn = function(){} 1 和函数声明方式的区别:函数声明语句是语句,函数表达式是表达式,除了表达式方式创建函数更灵活之外,比如支持立即函数和箭头函数,二者在解析时,在词法环境的注册规则也不一样,后面会讨论。
立即函数(IIFE)
(function(){})()// 用()告知JavaScript解析器把它解析为表达式而不是函数声明语句,避免因为被解析为函数声明并因为没有名字而报错。 1 告知JavaScript解析器将其识别为表达式而不是函数声明语句的方式有很多种,但这种就够用了并且阅读性最好,其它的方式在这里不做讨论。
箭头函数(Lambda):是函数表达式的简化版
const fn = () => (1) 1 箭头函数的简化不仅仅体现在定义方式上,在函数的调用上也有区别,比如函数运行时,它没有单独的this值,它的this指向与声明所在的上下文的this指向相同。

方式3:构造函数(通过Function构造函数创建)

const fn = new Function('a', 'b', 'return a + b') 1 函数都是内置函数对象 Function 的实例,所以它可以通过使用new关键字调用Function构造函数的方式得到函数对象。

三:JavaScript函数参数

0.认识形参和实参

形参是我们 定义函数时 所列举的变量。实参是我们 调用函数时 所传递给函数的值。

1.形实参 1 对 1 匹配

const av,bv = 1,2 function fn(a,b){} fn(av,bv) // 实参 av-> 形参a,实参 bv-> 形参b 123
形实参不对等时的匹配规则
形参数量大于实参数量,后续未被匹配的形参值为undefined。实参数量大于形参数量,不会匹配到任何一个形参,但是并不意味着丢失,因为还有隐式参数arguments,后面会讲到。

2.形实参 1 对 多 匹配(剩余参数)

为函数的最后一个命名参数前加上省略号(…)前缀,这个参数就变成了一个叫作剩余参数的数组,数组内包含着传入的剩余的参数,如下例:

// 使用ab当中更大的一个值加上除a、b匹配的实参外的后续所有实参的值 function fn(a,b,...rest) { const sum = a>b?a:b  for(i of rest){ sum += i } return sum } fn(1, 2, 3, 4) // 结果为9   123456789

3.形实参 1 对 0 匹配(默认参数)

function fn(a = 1,b = 2) {           return a+b; } fn(1) // 结果为3 1234

4.隐式参数this和arguments

隐式参数在函数声明中没有明确定义,在函数调用时也没有显示传入,但会默认传递给函数并且可以在函数内正常访问,同时在函数内可以像其他明确定义的参数一样引用它们,详细内容后面会再讨论。

最新回复(0)