通常而言,一个函数是一个子程序,他们可以被外部代码调用(亦或被滴管函数在内部调用)。和程序一样,函数是由一系列声明(被称为函数体function body)组合而成。值可以传递给函数,并且函数可以返回一个值。

在javascript中,函数是一个对象,因为她可以拥有属性和方法,就像对象一样。将函数和对象区分的是函数可以被调用,他们是函数对象(Function objects)。

描述

js中的所有函数都是函数对象Function object

函数和程序不一样,函数总是返回一个值,但是程序不一定。

为了返回一个值,一个班函数必须要有return的声明。一个没有return声明的函数将会返回一个默认值。

在用new关键字调用的构造函数中,默认值是this参数。对于其他的函数而言,默认值返回的是undefined。

函数调用个参数是函数的arguments属性。参数按值传递给函数,所以函数内部改变argument的值将不会影响函数外的参数的值。

然而对象的引用作为值传递给函数时,函数内部对于对象的改变将会影响到函数外部。

/* Declare the function 'myFunc' */
function myFunc(theObject) {
theObject.brand = "Toyota";
} /*
* Declare variable 'mycar';
* create and initialize a new Object;
* assign reference to it to 'mycar'
*/
var mycar = {
brand: "Honda",
model: "Accord",
year:
}; /* Logs 'Honda' */
console.log(mycar.brand); /* Pass object reference to the function */
myFunc(mycar); /*
* Logs 'Toyota' as the value of the 'brand' property of the object, as changed to by the function.
*/
console.log(mycar.brand);

关键字this并不指向当前正在执行的函数(指向的是windows对象),所以你必须通过名字将其指向函数对象。

定义函数

有以下方式来定义函数:

函数声明(function 声明)

function name([param[, param[, ... param]]]) {
statements
}
name
函数名
param
传递给函数的参数.参数个数的上限是255个。
statements
函数主体

函数表达式 (function 表达式)

function [name]([param[, param[, ... param]]]) {
statements
}
name
函数名. 可以省略,省略后被叫做匿名函数.
param
参数,上限255个参数
statements
函数主体

函数构造器

注意!使用Function构造器来创建函数不被推荐,因为它需要将函数主体作为一个字符串,这将阻止JS引擎优化并且会造成其他的问题。

new Function (arg1, arg2, ... argN, functionBody)
arg1, arg2, ... argN
0个或者多个参数名
functionBody
一个包含函数主体的字符串

还有一些新式的ECMAScript 6创建函数的方式,姐姐我不说了,等什么时候流行了再说 (✿◡‿◡)

函数属性

arguments对象

你可以在函数中使用arguments对象来指代函数的arguments属性。

  • arguments:一个类数组对象,包含了传递给正在执行的函数的参数。
  • arguments.callee : 正在执行的函数(API说不赞成这个属性被使用,但是仍然可以使用)
  • arguments.caller  : 废弃了,我不说了,和上面的作用一样
  • arguments.length: 传递给函数的参数个数

定义函数方法

getter和setter方法

你可以在任何支持新属性添加的内置对象或用户定义对象中定义getter(accessor方法)和 setter(mutator方法) 。定义setters和getters使用了对象字面量语法。

get

绑定一个对象属性到一个函数中,当读取一个属性的时候被调用。

set
绑定一个对象属性到一个函数中,当设置一个属性的时候被调用。

函数构造器VS函数声明VS函数表达式

比较如下:

定义一个函数使用Function构造函数,并且赋值给变量multiply

function multiply(x, y) {
return x * y;
}

一个匿名的函数表达式,并赋值给变量 multiply:

var multiply = function(x, y) {
return x * y;
};

一个函数表达式,并将函数命名为func_name,并赋值给变量multiply:

var multiply = function func_name(x, y) {
return x * y;
};

不同:

上述所有好像都在做着差不多的事情,但是有一些细微的不同。

在函数名和将函数赋值给的变量之间存在不同。

函数名是不可以改变的,但是变量是可以被再次赋值。

函数名只能在函数体里面使用。当尝试在函数外部使用时将会导致一个错误(如果函数名事先声明将build报错undefined)

例如:

var y = function x() {};
alert(x); // throws an error

在函数通过Function的toString方法序列化的时候同样也可以出现。

就像第四个例子展示的一样,函数名可以和函数赋值的变量不一样。他们之间没有相互关系。一个函数声明也可以创建一个拥有同样名字的变量。所以,和通过函数表达式被定义的函数不同,通过函数声明定义的函数可以在他们被定义的范围内通过他们的名字来获取函数本身。

通过new Function定义的函数没有函数名。但是在SpiderMonkey的js引擎中,函数序列化后的格式表示他们拥有anonymous的函数名

例如:alert(new Function())的输出结果是:

function anonymous() {
}

因为函数的确没有一个名称,anonymous并不是一个可以在函数内可以使用的变量(函数声明或者函数表达式中的函数名可以在函数体内使用),例如,下面的例子将会报错:

var foo = new Function("alert(anonymous);");
foo();

和用函数表达式或者Function构造器定义函数不同的是,通过函数声明定义的函数可以在函数声明前使用(使用了一个叫做函数声明提前的机制),例如:

foo(); // alerts FOO!
function foo() {
alert('FOO!');
}

一个通过函数表达式定义的函数继承了当前的环境。也就是说,这个函数形成了一个闭包。

然而,通过Function构造器定义的函数没有继承除了全局环境(所有函数都继承)以外的任何环境。

通过函数表达式和函数声明定义的函数只被解析一次,但是被函数构造器定义的函数被解析不仅一次。就是说,函数体字符串传递给Function 构造函数的时候必须被解析,此时将会调用构造函数(所以每次在使用函数构造器定义的函数的函数体的时候,都会调用构造函数)。虽然函数表达式会每次创建一个闭包,但是函数在调用个时候不会被每次解析,所以函数表达式仍然比"new Function(...)"要快,因此,函数构造器通常会尽可能的避免被使用。

需要注意的是,函数表达式和函数声明中嵌套着函数构造器定义的函数将不会被重复解析。如下图:

var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))();
foo(); // The segment "function() {\n\talert(bar);\n}" of the function body string is not re-parsed.

函数声明非常容易且常常是无意识的变成一个函数表达式。一个函数声明在下面任何一种情况将变成函数表达式:

1.成为表达式的一部分

2.不再是一个函数或者程序的“源元素(source element)”。一个source element是一个在程序亦或函数体中不内嵌的声明。

  • var x = ;               // source element
    if (x == ) { // source element
    x = ; // not a source element
    function boo() {} // not a source element
    }
    function foo() { // source element
    var y = ; // source element
    function bar() {} // source element
    while (y == ) { // source element
    function blah() {} // not a source element
    y++; // not a source element
    }
    }

    举例:

//函数声明
function foo() {}
// 函数表达式
(function bar() {})
// 函数表达式
x = function hello() {} if (x) {
//函数表达式
function world() {}
} //函数声明
function a() {
//函数声明
function b() {}
if () {
// 函数表达式
function c() {}
}
}

块级函数(block-level functions)

在严格模式下,从 ES2015 (ES6)开始,在一个块(花括号)里面的函数,它的作用域将属于那个块。

在ES6之前,块级函数禁止在严格模式下使用。

'use strict';

function f() {
return ;
} {
function f() {
return ;
}
} f() === ; // true // f() === 2 in non-strict mode

块级函数在非严格模式下使用

简而言之:不要用!

在非严格模式下,在花括号中的函数声明将会表现的非常奇怪。如下:

if (shouldDefineZero) {
function zero() { // DANGER: compatibility risk
console.log("This is zero.");
}
}

ES2015定义了如果shouldDefineZero(应该定义zero么)是false,那么说明zero没有被定义,那么花括号里面的代码也不会执行。

但是,这是新标准的一部分。历史上是遗留的没有定义的标准,并且一些浏览器将定义zero不管判断语句执行成功与否。

在严格模式下,所有的浏览器都支持ES2015标准,所以他们都将按照一样的方式执行:zero在只有shouldDefineZero为true的时候才能执行,并且只在if语句块中执行。

一个更加安全的做法是将将函数表达式赋值给一个变量。

var zero;
if () {
zero = function() {
console.log("This is zero.");
};
}

判断一个函数方法是否存在

你可以通过typeof判断一个函数是否存在。

在下面的方法中,进行了一个用于判断window对象是否有noFunc的属性,并且是noFunc是一个函数类型的测试。

if ('function' == typeof window.noFunc) {
// use noFunc()
} else {
// do something else
}

注意在if的条件判断中,只是引用了noFunc函数名,但是函数名后面没有(),也就是说实际上没有执行。

原文链接:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions

Function javascript的更多相关文章

  1. javascript的 Object 和 Function

    一. javascript 的 内置对象: Object 和 Function javascript所有东西,包括 Function 都是对象 . Array  其实是一个 Function 类型的对 ...

  2. javascript 中 function bind()

    Function bind() and currying <%-- All JavaScript functions have a method called bind that binds t ...

  3. javascript中的操作符详解1

    好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...

  4. Javascript常用方法函数收集(二)

    Javascript常用方法函数收集(二) 31.判断是否Touch屏幕 function isTouchScreen(){ return (('ontouchstart' in window) || ...

  5. javascript常用方法函数收集

    收集了一些比较常用的javascript函数. 1.字符串长度截取 function cutstr(str, len) { var temp, icount = 0, patrn = /[^\x00- ...

  6. javascript版Ajax请求

    什么是Ajax请求,Ajax也就是“Asynchronous JavaScript and XML”(异步JavaScript和XML),无刷新数据读取.能减少流量的消耗,也提高了浏览的流畅性,给用户 ...

  7. Java基础 —— JavaScript

    Javascript:基于对象与事件驱动的脚本语言,主要用于客户端 特点: 交互性:信息动态交互. 安全性:不能访问本地硬盘. 跨平台性:只要有浏览器就支持Javascript,与平台无关. Java ...

  8. 100个直接可以拿来用的JavaScript实用功能代码片段(转载)

    把平时网站上常用的一些实用功能代码片段通通收集起来,方面网友们学习使用,利用好的话可以加快网友们的开发速度,提高工作效率. 目录如下: 1.原生JavaScript实现字符串长度截取2.原生JavaS ...

  9. Javascript核心概述 - 深入了解javascript

    /* 一.执行上下文:堆栈(底部全局上下文+顶部当前活动上下文) */ /* 二.变量对象: 变量根据执行上下文,找到数据存储位置,这种机制叫变量对象 1. 变量都要var定义,且都不能delete ...

随机推荐

  1. 【Exception】查看异常出现在具体的文件名/类名/方法名/具体行号

    今天在处理异常日志保存过程中,想要获取到异常抛出在具体在那个文件,哪个类下的哪个方法中的具体第几行,所以具体实现如下 try{ Integer adminID = Integer.parseInt(a ...

  2. Raid分类说明 (from mongodb权威指南)

    RAID(Redundant Array of Independent Disk,独立磁盘冗余阵列,旧称Redundant Array of InexpensiveDisk,廉价磁盘冗余阵列) 是一种 ...

  3. IntelliJ IDEA 10.5.1 引用外部Jar包

    具体步骤: File -> Project Structure (ctrl + shift + alt + s ) -> Module -> Dependencies -> A ...

  4. RecyclerView onItemClick button和布局都有单击事件时的处理方式

    RecyclerView为了给开发人员提供更大的自由度.没有默认的提供onItemClick接口. 网上有一种比較简单的实现方式 , 适用于不须要针对item里面某个button做特殊处理的情况 我眼 ...

  5. C 标准库 - <stdarg.h>

    C 标准库 - <stdarg.h> 简介 stdarg.h 头文件定义了一个变量类型 va_list 和三个宏,这三个宏可用于在参数个数未知(即参数个数可变)时获取函数中的参数. 可变参 ...

  6. Android 音频的播放之二MediaPlayer

    MediaPlayer类可用于控制音频/视频文件或流的播放.关于怎样使用这个类的方法还能够阅读VideoView类的文档. 1.状态图 对播放音频/视频文件和流的控制是通过一个状态机来管理的. 下图显 ...

  7. 函数式编程( Functional)与命令式编程( Imperative)对比

    1.函数式编程带来的好处 函数式编程近些年异军突起,又重新回到了人们的视线,并得到蓬勃发展.总结起来,无外乎如下好处: 1.减少了可变量(Immutable Variable)的声明,程序更为安全.  ...

  8. Android_动态权限管理的解决方式

    本博文为子墨原创.转载请注明出处! http://blog.csdn.net/zimo2013/article/details/50478201 1.前言 (1).因为MIUI等部分国产定制系统也有权 ...

  9. 深入Garbage First垃圾收集器(二)背景

    G1 GC是目前Java HotSpot虚拟机最新的垃圾收集器. 它是一种压缩型收集器,其基本原则是首先收集尽可能多的垃圾,因此被命名为"Garbage First" GC. G1 ...

  10. Webkit JNI

    WebCoreFrameBridge.cpp BrowserFrame通过jni传下来的调用都会调用到WebCoreFrameBridge.cpp中的对应函数中,其他webkit的模块想回调信息给Br ...