讲清楚之 javascript 函数

发布时间:2019-08-14 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了讲清楚之 javascript 函数脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

函数

之前几节中围绕着函数梳理了 this、原型链、作用域链、闭包等内容,这一节梳理一下函数本身的一些特点。

@L_512_1@script 中函数是一等公民。 并且函数也是对象,因为它们可以像任何其他对象一样具有属性和方法。它们与其他对象的区别在于函数可以被调用。简而言之,它们是 Function 对象。

一个函数是可以通过外部代码调用的一个“子程序”,函数内部包含了执行语句或表达式。每个自定义函数都是Function的实例,并继承Function的所有属性和方法,而Function 是语言本身提供的编程接口。

function foo (name) {
    console.LOG(`hello, @H_360_36@${name}`)
}
VAR res = foo(`小明`) // 'hello, 小明'
console.log(res)

调用函数时,传递给函数的值被称为函数的实参(值传递),对应位置的函数参数名叫作形参。如果实参是一个包含原始值(数字,字符串,布尔值)的变量,则就算函数在内部改变了对应形参的值,返回后,该实参变量的值也不会改变。如果实参是一个对象引用,则对应形参会和该实参指向同一个对象。假如函数在内部改变了对应形参的值,返回后,实参指向的对象的值也会改.(欢迎查看参数传值一节)

如果函数内部没有通过return返回一个值,则函数会默认返回undefined.

函数在实际开发中承担着代码分块、 功能封装等任务

函数定义

// 函数申明
foo()
let a = 1
function foo () {
    console.log(a)
}

// 函数表达式 (函数变量)
let too = function (){
  console.log('hello')
}
too()

// Function 构造函数实例化一个函数
let bar = new Function('console.log("hello")')
bar()

// 箭头函数
let fns = () => {
    console.log('hello')
}
fns()
需要注意的是函数申明函数表达式在变量提升时的区别,强烈建议阅读变量对象相关内容:详情。同时函数申明的函数名称不能被改变,而函数表达式赋值给的变量可以被重新赋值。

函数的各种定义方式就不深入,这里需要注意的是通过使用构造函数(new Function())方式创建的函数,在每次调用的时候都会解析一次。所以不推荐使用 Function 构造函数创建函数, 因为它需要的函数体作为字符串可能会阻止一些 JS 引擎优化,也会引起浏览器资回收等问题。

arguments

argumentsthis一样是函数提供给函数内部使用的一个属性(ES6中箭头函数没有)。通过arguments我们可以获取调用函数时传递进来的实参, 该属性是一个类数组对象,我们可以像数组一样进行数值的读取。

function foo () {
    let a = arguments[0] // 获取函数的第一个参数
    let b = arguments[1] // 获取函数的第二个餐宿
    // 遍历函数的所有参数
    for (let arg in arguments) {
        console.log(`${arg}: ${arguments[arg]}`)
    }
    arguments[2] = 1122
}

foo(123)

虽然arguments是类似于数组,但是除了通过索引获取元素length属性外,不能使用pushpop等方法。如果确实要进行修改操作,可以将其转换为真正的数组:

let args = Array.PRototyPE.slice.call(arguments)
let args = [].slice.call(arguments)

// ES2015
let args = Array.From(arguments)

自执行函数

把函数定义和函数执行结合到一起就是立即执行函数,也叫自执行函数。

官方语中叫做 IIFE( 立即调用函数表达式),是在定义时就会立即执行的函数。被称为自执行匿名函数的设计模式,主要包括两部分:

  • 第一部分是包围在 括号运算() 里的一个匿名函数,这个匿名函数拥有独立的词法作用域。这不仅避免了外界访问此 IIFE 中的变量,而且又不会污染全局作用域。借用这个特性我们可以对局部功能进行封装,只暴露很少的方法给外部环境,这也是很多第三方库的封装方法之一。
  • 第二部分再一次使用 () 创建了一个立即执行函数表达式,JavaScript 引擎到此将直接执行函数。

当函数变成立即执行的函数表达式时,表达式中的变量不能从外部访问:

(function () {
    var a = 1
})()
console.log(a) // a is not defined

将 IIFE 分配给一个变量,不是存储 IIFE 本身,而是存储 IIFE 执行后返回的结果:

let bar = (function (){
           let a = 123
           return a
           })()
console.log(bar) // 123

别外自执行函数还有一些其他使用方式:

// 下面2个括弧()都会立即执行
(function(){ /* code */ }());
(function(){ /* code */ })();

// 由于括弧()和JS的&&,异或,逗号等操作符是在函数表达式和函数声明上消除歧义的
// 所以一旦解析器知道其中一个已经是表达式了,其它的也都默认为表达式了

var i = function(){ /* code */ }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

// 如果你不在意返回值,或者不怕难以阅读
// 你甚至可以在function前面加一元操作符号

!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

// 上面这种使用一元表达式这种方式其实是不太常见的
// 而且有时候肯定在一些场景下存在一些弊端,因为一元表达式会有一个不为undefined的返回值
// 要想返回值为undefined,那么最保险的就是使用void关键字

void function(){/* code */}();

()左边必须是一个函数表达式,而不是一个函数申明。自执行函数也会用在模块封装的场景下。

闭包

函数和函数声明时的词法作用域形成闭包。我们可以使用闭包来保存变量、封装不需要暴露的私有属性和方法。

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}

var foo = checkscope();
foo(); // "local scope"

彻底理解闭包的最好途径就是理解闭包的由来,闭包的产生和作用域链有密切关系。在作用域链一节已经梳理过闭包的原理。

函数式编程

未完成

脚本宝典总结

以上是脚本宝典为你收集整理的讲清楚之 javascript 函数全部内容,希望文章能够帮你解决讲清楚之 javascript 函数所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。