[JavaScript]JavaScript中的函数

Posted 小粒旬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JavaScript]JavaScript中的函数相关的知识,希望对你有一定的参考价值。

关于javascript中函数的学习:
MDN
阮一峰老师的教程

关于函数的定义:

阮一峰老师:函数是一段可以反复调用的代码块。函数还能接受输入的参数,不同的参数会返回不同的值。

MDN:Function 构造函数 创建一个新的Function对象。 在 JavaScript 中, 每个函数实际上都是一个Function对象。

函数的声明方式和name

函数的声明方式有目前来说有5种,每一个函数都有他的一个name属性(包括匿名函数),要注意。

  • 具名函数
function fn(x,y) {
    console.log(x + y)
}
fn.name //"fn"
  • 匿名函数
var fn
f = function(x,y){
    console.log(x + y)
}
f.name //"f"
  • 具名函数赋值
var fn
fn = function f(x,y) {
    console.log(x + y)
}
fn.name //"f"
f.name  //f is not defined
  • window.Function
var f = new Function(‘x‘,‘y‘,‘return x+y‘)
f.name // "anonymous"
  • 箭头函数
var fn = (x,y) => {return x + y}
f.name  //"fn"

现在最常用的就是具名函数和箭头函数。

函数的调用和call()

在声明了一个函数之后,我们就可以调用这个函数了。

但是,我们在调用一个函数的时候,究竟发生了什么,搞清楚其中的机制,可以帮助我们更深入地了解函数。

现梳理一下我的关于函数调用的思路:

首先我们声明了一个函数:

var fn = function(x,y){
    retrun x + y
}

因为Function也是属于一种对象,所以这个变量就有了一个地址A,这个地址A就指向堆内存中的对象B,对象B中就存放着我们的函数参数与函数体。

如图所示:

技术分享图片

在这个对象B中的__proto__指向了Function.prototype,在Function.prototype中有一个特殊的call()属性,这个方法对我们“调用函数”的这个动作来说至关重要。

每次调用函数时,其实就是使用这个call()属性来执行函数体中的内容。

技术分享图片

由于JavaScript这门语言的历史遗留问题,fn.call()才是函数真正的调用方法。

注意

fn(1,2)等价于fn.call(undefined,1,2)

fn(1,2)相当于一种语法糖,但是call()方法能让学习者更好地理解关于函数中的this和arguments概念,所以建议在学习过程中函数调用使用call(),直到掌握this为止。

函数中的this和arguments

函数中的 this指的到底是什么?

先下结论:this指的就是call()中的第一个参数,第一个参数往后都是arguments。

对此,我的理解是,他指的是一种域,一种范围(可适当理解为函数的作用域),结合call()来看的话就很清晰明了了。

且看,我们声明了一个函数:

var fn = function(x,y){
    console.log(‘x:‘+x,‘y:‘+y)
    console.log(this)
}
fn(1,2)
fn.call(undefined,1,2)

两者的运行结果都是:

技术分享图片

技术分享图片

两者的this都是一个window全局对象,我们来转变一下:

var a = 3
var obj = {
    a: 4
}
var fn = function(x,y){
    console.log(‘x:‘+x,‘y:‘+y)
    console.log(this.a)
}
fn(1,2)
fn.call(obj,1,2)

运行结果如下:

技术分享图片

我们可以看到,因为我们在代码前面声明了一个赋值为3的全局对象a,第一个fn的调用中的this没有改变,依然是window全局对象,所以函数fn中的this.a找的是全局作用域中的a,也就是打印出了3。

我们还在代码前面声明了一个对象,其中包含了一个key a,key的值为 4,第二个fn调用的时候,我们把对象obj当成参数传给了fn,这个对象 obj就变成了fn的 this!!所以代码运行时,函数fn中的this.a找的就是对象obj中的a。

因为正常的函数调用fn()简化了传入this的一步,而fn.call()则需要把this作为参数传入,所以使用call()来学习this 是有好处的。

注意

普通模式与严格模式

在普通模式和严格模式下,this表现会有所不同:

// 严格模式
var fn = function(x,y){
    ‘use strict‘
    console.log(‘x:‘+x,‘y:‘+y)
    console.log(this)
}
fn.call(undefined,1,2)
fn.call(1,1,2)

技术分享图片

// 普通模式
var fn = function(x,y){
    console.log(‘x:‘+x,‘y:‘+y)
    console.log(this)
}
fn.call(undefined,1,2)
fn.call(1,1,2)

技术分享图片

在普通模式下,如果this是undefined,浏览器会自动把this变成Window;如果是其他的值,则会打出一个对象(比如说1,则会打出一个Number 1的对象);

严格模式下,如果this是undefined,他就是undefined,如果是其他的值,则会打出这个值本身。

arguments

arguments指的就是函数的参数。

使用arguments可以打出一个伪数组,伪数组就是像数组,但是__proto__中没有Array.prototype的对象。

// 普通模式
var fn = function(x,y){
    console.log(‘x:‘+x,‘y:‘+y)
    console.log(arguments)
}
fn.call(undefined,1,2)

技术分享图片

下一篇博文会接着总结一下函数中的作用域和闭包。



以上是关于[JavaScript]JavaScript中的函数的主要内容,如果未能解决你的问题,请参考以下文章

javascript笔记

JavaScript计时事件

JavaScript——闭包

Mootools 是不是 100% 防止 javascript 关闭?

Javascript 的 arguments 参 数

从延迟处理讲起,JavaScript 也能惰性编程?