搞定JS函数

每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.函数名实际上是指向函数对象的指针.

函数声明:

function sum( num1,num2) {
	return num1+num2;
}
var sum = sum(1,2);  //3

函数声明提升: 上面这个例子是函数声明在前,调用在后,但是js引擎能把函数声明提到顶部.

函数表达式:  

var sum = function(num1,num2) {
	return num1+num2;
}
console.log(sum(1,2));

function后面没有变量名,sum就相当于变量名,直接调用.但是不能在调用之后才定义,会报 "Uncaught TypeError: undefined is not a function"错误.

说说函数名后面的 ( )

以上面的sum(num1,num2)为例

  • sum();      执行函数
  • sum:      没有括号是访问函数的指针不执行函数

arguments对象和this对象

  • arguments对象存放着函数的所有参数,类似数组但不是数组,
  • 函数内部的this引用的是函数据以执行的环境变量,当在全局作用域中调用函数时,this对象引用的就是window对象.

arguments.callee属性:指向拥有这个arguments对象的函数.在递归的时候用到

function fac(num) {
	if(num<=1){
		return 1;
	}else {
		return num* arguments.callee(num)
	}
}

 使用arguments.callee,函数内部调用和函数本身的名字不会有耦合.

 函数传参:

题目描述

将数组 arr 中的元素作为调用函数 fn 的参数 
输入例子:
argsAsArray(function (greeting, name, punctuation) {return greeting + ', ' + name + (punctuation || '!');}, ['Hello', 'Ellie', '!'])
输出例子:
Hello, Ellie!
function argsAsArray(fn, arr) {
	return  fn(arr[0], arr[1], arr[2]);
}

题目描述 考察:call() apply() bind() 改变上下文this

将函数 fn 的执行上下文改为 obj 对象 
输入例子:
speak(function () {return this.greeting + ', ' + this.name + '!!!';}, {greeting: 'Hello', name: 'Rebecca'})
输出例子:
Hello, Rebecca!!!
//三种方案
//apply
function speak(fn, obj) {    return fn.apply(obj);}
//call
function speak(fn, obj) {    return fn.call(obj);}
//bind
function speak(fn, obj) {    return fn.bind(obj)();}

注意:在JavaScript中,函数是一种对象,其上下文是可以变化的,对应的,函数内的this也是可以变化的,函数可以作为一个对象的方法,也可以同时作为另一个对象的方法,可以通过Function对象中的call或者apply方法来修改函数的上下文,函数中的this指针将被替换为call或者apply的第一个参数。将函数 fn 的执行上下文改为 obj 对象,只需要将obj作为call或者apply的第一个参数传入即可。

题目描述 考察:var obj = {},var obj = new Object();

完成函数 createModule,调用之后满足如下要求:
1、返回一个对象
2、对象的 greeting 属性值等于 str1, name 属性值等于 str2
3、对象存在一个 sayIt 方法,该方法返回的字符串为 greeting属性值 + ', ' + name属性值
function createModule(str1,str2) {
	var newObj = {
		greeting:str1,
		name:str2,
		sayIt:function(){
			return  this.greeting+', '+this.name; //注意this
		}
	}
	return newObj;
}

题目描述

给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。 
输入例子:
var C = function(name) {this.name = name; return this;}; var obj1 = new C('Rebecca'); alterObjects(C, 'What\'s up'); obj1.greeting;
输出例子:
What's up
function alterObjects(constructor, greeting) {
	constructor.prototype.greeting = greeting;
}

原型链:bhggg

 

题目描述 考察:递归 arguments.callee()函数

 

用 JavaScript 实现斐波那契数列函数,返回第n个斐波那契数。 f(1) = 1, f(2) = 1 等
function fibonacci(n) {
    if(n==1||n==2) {
    	return 1;
    } else {
    	return arguments.callee(fibonacci(n-1))+arguments.callee(fibonacci(n-2));
    }
}

注意: 函数递归应该始终使用 argument.callee来递归调用自身,不要使用函数名-----函数名可能会变化.  

    闭包

  先来讲一讲"作用域"的概念,再了解闭包是什么."作用域",举个例子,简单来说就是,外部函数包含内部函数,内部函数可访问外部的变量,而外部的却不能访问内部的.在函数中访问一个变量时,就会从作用域中搜索具有相应名字的变量,作用域链本质上是 一个指向变量对象的指针列表,访问是线性的有次序的. 闭包会携带包含它的函数的作用域,内部函数可以访问外部环境变量对象.但是闭包也因比其他函数占用更多的内存带来了不好的一面,应慎重使用闭包.

函数中声明的变量是局部变量,在函数外部是没有办法访问的.下面拿自增的举例

function box(){
	var age = 100;
	return age;
}
alert(age);   // "Uncaught ReferenceError: age is not defined"

  而利用闭包可以返回局部变量:

//使用匿名函数实现局部变量驻留内存
function box() {
	var age = 100;
	return function(){
		age++;
		return age;
	};
}
var b = box();
alert(b());   //100
alert(b());   //101
alert(b());   //102
alert(b());   //103
alert(b());   //104
b = null; //解除引用,等待垃圾回收

  

 

 

 

 

 

 

 

posted @ 2017-03-23 19:50  进阶乐园  阅读(3893)  评论(0编辑  收藏  举报