JavaScript基础篇(四)— — 函数
来源:互联网 发布:linux系统yum指令 编辑:程序博客网 时间:2024/05/24 16:14
一、函数定义
函数重复声明,后一次的函数声明会覆盖了前面一次
- 函数声明语句
function plus(x ,y) {}
声明式会让函数前置,所以在声明函数之前调用它也是可以调用成功的
* 函数定义表达式
var plus = function (x, y) {}
- Function构造函数
var add = new Function('x', 'y', 'return (x + y)' );// 等同于function add(x, y) { return (x + y);}
二、函数调用
- 作为函数调用
function func(){};func();
- 作为方法调用
obj = { };obj.funX = function() {};obj.funX();
- 通过call和apply间接调用函数(改变this)
call 和 apply带有多个参数,call和apply把当前函数的this指向第一个参数给定的函数或对象中,并传递其余所有的参数作为当前函数的参数。
var O = function () { this.foo = 'hello'; this.hello = function () { return 'world'; }};var fn = function () { console.log('call', this);};var o = new O();fn.call(o);//此时fn的this指向o
call和apply的不同之处,在于call传递的参数是作为arguments依次传入的,例如: fn.call(o, 1, 2, 3);
而apply传递的参数是以一个数组的方式传入的,例如: fn.apply(o, [1, 2, 3]);
三、参数
1、当传入参数少于函数声明的参数时,留空的参数的值是undefined。
2、JavaScript允许传入参数的个数大于声明时制定的参数个数。可以用arguments来访问这些参数
function f(){ for(var i = 0; i < arguments.length ; i++) { console.log(arguments[i]); }}f(1,2,3,4,5,6);//打印出1,2,3,4,5,6
3、默认值
function f(a){ (a !== undefined && a !== null) ? a = a : a = 1; return a;}
四、作为值的函数
javascript中的函数可以作为值来传递
function square(x) { return x * x;}var s = square;s(4);
五、函数名的提升
f();var f = function (){};// TypeError: undefined is not a function
上面的代码等同于下面的形式。
var f;f();f = function () {};
第二行中调用f的时候,f只是被声明了,还没有被赋值,等于undefined,所以会报错。
六、函数作用域
Javascript只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。
1、函数内部定义的变量,会在该作用域内覆盖同名全局变量。
var v = 1;function f(){ var v = 2; console.log(v);}f() // 2v // 1
2、对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量
if (false) { var x = 5;}console.log(x); // 5
3、函数本身的作用域
函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。
var a = 1;var x = function () { console.log(a);};function f() { var a = 2; x();}f() // 1
上面代码中,函数x是在函数f的外部声明的,所以它的作用域绑定外层,内部变量a不会到函数f体内取值,所以输出1,而不是2。
很容易犯错的一点是,如果函数A调用函数B,却没考虑到函数B不会引用函数A的内部变量。
var x = function () { console.log(a);};function y(f) { var a = 2; f();}y(x)// ReferenceError: a is not defined
上面代码将函数x作为参数,传入函数y。但是,函数x是在函数y体外声明的,作用域绑定外层,因此找不到函数y的内部变量a,导致报错。
同样的,函数体内部声明的函数,作用域绑定函数体内部。
function f1() { var x = 1; function f2() { console.log(x); } return f2;}var x = 2;var ff = f1();ff() // 1
上面代码中,函数f1内部声明了一个函数bar,bar的作用域绑定foo。当我们在foo外部取出bar执行时,变量x指向的是foo内部的x,而不是foo外部的x。正是这种机制,构成了下文要讲解的“闭包”现象。
七、闭包
《学习Javascript闭包(Closure)》
接上面的代码
闭包就是函数f2,即能够读取其他函数内部变量的函数。由于在JavaScript语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从f2可以得到f1的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。请看下面的例子,闭包使得内部变量记住上一次调用时的运算结果。
function createIncrementor(start) { return function () { return start++; };}var inc = createIncrementor(5);inc() // 5inc() // 6inc() // 7
上面代码中,start是函数createIncrementor的内部变量。通过闭包,start的状态被保留了,每一次调用都是在上一次调用的基础上进行计算。从中可以看到,闭包inc使得函数createIncrementor的内部环境,一直存在。所以,闭包可以看作是函数内部作用域的一个接口。inc始终在内存中,而inc的存在依赖于createIncrementor,因此也始终在内存中,不会在调用结束后,被垃圾回收机制回收。
闭包的另一个用处,是封装对象的私有属性和私有方法。
function Person(name) { var _age; function setAge(n) { _age = n; } function getAge() { return _age; } return { name: name, getAge: getAge, setAge: setAge };}var p1 = person('张三');p1.setAge(25);p1.getAge() // 25
闭包应用场景
封装
闭包缺点
1、空间浪费 2、内存泄漏 3、性能消耗
解决方法是,在退出函数之前,将不使用的局部变量全部删除。
八、立即调用的函数表达式(IIFE)
只对匿名函数使用这种“立即执行的函数表达式”。它的目的有两个:一是不必为函数命名,避免了污染全局变量;二是IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。
(function() { /* code */ }());// 或者(function() { /* code */ })();
参考链接:
1、http://javascript.ruanyifeng.com/grammar/function.html
2、http://pij.robinqu.me/JavaScript_Core/JavaScript_Basics/Function.html
- JavaScript基础篇(四)— — 函数
- 四、程咬金——JavaScript基础
- JavaScript快速入门(四)——JavaScript函数
- JavaScript基础篇(五)— — 函数(1)
- Javascript基础——详解function函数
- JavaScript基础——函数表达式
- JavaScript入门——基础函数示例
- 【JavaScript 4—基础知识点】:函数
- JavaScript基础学习笔记(四)——Object类型
- javascript面向对象技术基础(四)(类、构造函数、原型)
- javascript(基础整理四)
- JavaScript-基础(四)
- javaScript基础 (四)
- JavaScript程序设计基础篇:函数
- JavaScript学习笔记(四)——函数对象1
- JavaScript学习笔记四——Eval函数
- JavaScript学习笔记四——Eval函数
- Javascript面向对象(四)——函数原型
- BZOJ 2304: [Apio2011]寻路
- 海量数据处理面试题
- windows核心编程之服务(services)、函数(functions) 、例程(routines)
- 【收藏用】--切勿转载JAVA 使用Dom4j 解析XML
- PopuoWindow弹出时报BadTokenException的解决方案
- JavaScript基础篇(四)— — 函数
- Masonry之初体验
- DES加密算法
- hdoj1012
- undefined reference to 'socket@12'编译socket出错codeblocks
- 红黑树
- UIViewController之间的传值 6种
- ConcurrentHashMap原理分析
- LeeCode-Same Tree