您的位置:首页 > Web前端 > JavaScript

js函数总结

2016-02-22 10:02 591 查看

1.函数声明提升

函数声明与变量声明会被JavaScript引擎隐式地提升到当前作用域的顶部,但是只提升名称不会提升赋值部分。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>函数声明提升</title>
</head>
<body>
<script type="text/javascript">
fn();//我是函数声明
var fn=function(){
console.log("我是函数表达式");
};
function fn(){
console.log("我是函数声明");
}
fn();//我是函数表达式
/*
实际执行顺序:
var fn;
function fn(){
console.log("我是函数声明");
}
fn();//我是函数声明
fn=function(){
console.log("我是函数表达式");
};
fn();//我是函数表达式
*/
/*
函数表达式最大的问题,在于js会将此代码拆分为两行代码分别执行。
所以函数声明覆盖了变量声明
*/
</script>
</body>
</html>

<pre name="code" class="html">//封装函数
//1、传统方式封装
//该方式允许封装的函数"先调用,后声明",该过程称为函数的"预加载"
//预加载:程序代码没有执行之前,函数的声明先进入内存
//表面上是函数调用在前、函数声明在后,本质上是函数声明在前、调用在后
//预加载条件:"声明和调用"必须在同一个script标记里面
//原因是每个script标记是独立加载、解释和运行的
//getInfo();//也可以成功调用
function getInfo(){
console.log('beijing');
}
getInfo();
//js中一切都是对象
//函数也是对象(数据类型的一种)
//2、变量赋值方式声明函数,就是函数表达式(不支持函数预加载)
//getWeather();//TypeError: getWeather is not a function
var getWeather=function(){
console.log('晴朗');
}

getWeather();//晴朗




2.函数-callee

arguments.callee是一个指向正在执行的函数的指针

function jisuan(n){
if(n<=1){
return 1;
}else{
//return n*jisuan(n-1);//TypeError: jisuan is not a function
return n*arguments.callee(n-1);
}
}
var js=jisuan;
jisuan=null;
console.log(js(5));//120

3.caller属性

caller属性保存着调用当前函数的函数引用

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>caller属性</title>
</head>
<body>
<script type="text/javascript">
function outer(){
inner();
}
function inner(){
//inner.caller指向outer
console.log(inner.caller);// outer()
//alert(inner.caller);//显示outer函数的源代码
//这样写实现了更松散的耦合
alert(arguments.callee.caller);//显示outer函数的源代码
}
outer();
</script>
</body>
</html>


4.匿名函数自执行

//变量赋值声明一个函数
var getInfo=function(){
console.log("Today is sunshine");
}
//var getInfo="okok";//使用一个同名的getInfo变量把上面的函数给污染覆盖
getInfo();//Today is sunshine

//使得以下匿名函数发生执行
//特点:程序代码没有停顿,立即执行
//好处:可以避免变量污染
(function(){
console.log("I am no name function");
})();//I am no name function


5.arguments

arguments属性是一个类数组对象,保存着传入函数的所有参数,主要用途就是保存函数参数

arguments有一个callee属性,该属性是一个指针,指向拥有arguments属性的函数

//arguments关键字 在函数内部可以接受传递进来的实参
//可以通过数字下标形式来访问各个实参信息
//其length属性可以获得实参个数
function getInfo(){
var num=arguments.length;
//根据传递参数的个数做灵活处理
if(num==0){
console.log('个人信息');
}else if(num==1){
console.log('名字:'+arguments[0]);
}else if(num==2){
console.log('名字:'+arguments[0]+' age:'+arguments[1]);
}else if(num==3){
console.log('名字:'+arguments[0]+' age:'+arguments[1]+' job:'+arguments[2]);
}
//console.log('名字:'+arguments[0]+' age:'+arguments[1]+' job:'+arguments[2]);
//console.log(arguments);
}
//同一个函数调用的时候,由于传递不同个数的实参,最终导致的结果也不一样
//其实是模仿方法重载(定义了许多名称一致的方法,这些方法的参数个数或者参数类型不一样
//这些方法就构成了重载)
//在php和js中没有重载
//
//重写:子类的同名方法去覆盖父类的同名方法
//重载:一个类里面有许多同名的方法
getInfo();
getInfo('liujie');
getInfo('liujie',23);
getInfo('liujie',23,'student');

6.apply和call

apply()和call()方法。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。

apply()方法接收两个参数:一是在其中运行函数的作用域;二是参数数组。第二个参数可以是Array的实例,也可以是arguments对象。

apply()和call()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于call()方法而言,第一个参数this值没有变化,变化的是其余参数都是直接传递给函数,参数必须逐个列举出来。

第一个参数传null或undefined时,将是JS执行环境的全局变量。浏览器中是window,其它环境(如node)则是global。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>apply和call</title>
</head>
<body>
<script type="text/javascript">
/*apply()和call()方法真正强大的地方是能够扩充函数赖以运行的作用域
*/
var color="red";
var o={color:"blue"};
function sayColor(){//全局函数
console.log(this.color);
}
sayColor();//red  //这里在全局环境调用,this.color会转化为window.color
sayColor.call(this);//red   显示的在全局作用域中调用函数
sayColor.call(window);//red  显示的在全局作用域中调用函数
sayColor.call(o);//blue  使用call()方法将函数内部的this指向了对象o
</script>

</body>
</html>


7.bind方法

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>bind方法</title>
</head>
<body>
<script type="text/javascript">
/*
bind方法的主要作用是将函数绑定至某个对象
*/
function f(y){//待绑定的函数
return this.x+y;
}
var o={x:1};//将要绑定的对象
var g=f.bind(o);//通过调用g(x)来调用o.f(x)
console.log(g(2));//3

var color="red";
var o={color:"blue"};
function sayColor(){
console.log(this.color);//blue
}
var objectSayColor=sayColor.bind(o);
//sayColor()调用bind()并传入对象o,创建了objectSayColor()函数
//objectSayColor()函数的this值等于o
objectSayColor();
</script>
</body>
</html>


8.私有变量

/*
任何在函数中定义的变量,都成为私有变量,因为在函数外部无法访问它们
私有变量包括:函数参数、局部变量以及函数内部定义的其他函数
*/
function Person(name){
//在构造函数内部定义了两个特权方法:getName()和setName()。这两个方法都可以在构造函数外部使用,而且都有权访问私有变量name
this.getName=function(){
return name;
};
this.setName=function(value){
name=value;
};
}
var person1=new Person("liujie");
console.log(person1.getName());//liujie
person1.setName("liujiejie");
console.log(person1.getName());//liujiejie


9.块级作用域

function outputNumbers(count){
//由于JS中没有块级作用域,所以这里的i实际是在包含函数outputNumbers创建的,而不是在块语句中创建的
//在java、C++等语言中,变量i只会在for循环的块语句中有定义,循环一旦结束,变量i就会被销毁
//而在js中,变量i是定义在outputNumbers()函数的活动对象中的,因此,从它开始有定义起,就可以在函数内部随处访问它
for(var i=0;i<count;i++){
console.log(i);//0、1、2、3、4
}
console.log("块语句外:"+i);//5
}
outputNumbers(5);

10.模仿块级作用域

/*
匿名函数可以用来模仿块级作用域

(function(){
//这里是块级作用域,通常称为私有作用域
//将函数声明放在圆括号中表名它是一个表达式
})();
*/
function outputNumbers(count){
(function(){
//这里在for循环的外部插入了一个私有作用域,在匿名函数中定义的任何变量,都会在执行结束时被销毁。因此,变量i只能在循环中使用,使用后即被销毁。
for(var i=0;i<count;i++){
console.log(i);//0、1、2、3、4
}
})();
console.log(i);//ReferenceError: i is not defined
}
outputNumbers(5);


11.静态方法

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>静态方法</title>
</head>
<body>
<script type="text/javascript">
function Person(name){
this.name=name;
this.sayName=function(){
console.log(this.name);
}
}
Person.sayAge=function(){//静态方法
console.log(1);
};
var person1=new Person('lisi');
person1.sayName();//lisi
Person.sayAge();//1
</script>
</body>
</html>


静态方法可以通过构造函数名来调用

12.用apply改变函数作用域

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>用apply改变函数作用域</title>
</head>
<body>
<script type="text/javascript">
/*
apply、call、bind都有个作用就是改变作用域,这里用apply将foo函数的作用域指向obj对象,同时传入参数。
再简单分析一下bind函数内部的嵌套,执行bind函数的时候返回的是一个匿名函数,所以执行bar(3)的时候实际上是执行的bind内部的匿名函数,返回的是之前传入的foo函数的执行结果。
函数没有返回值的情况下默认返回undefined。
*/
function foo(somthing){
console.log("一:"+this.a, somthing);//一:2 3
}
function bind(fn, obj){
return function(){
return fn.apply(obj, arguments);
}
}
var obj = {
a:2
}
var bar = bind(foo, obj);//foo中的this指向了obj
/*
bar=function(){
return fn.apply(obj, arguments);
}
*/
var b = bar(3);
console.log("二:"+b);//二:undefined
</script>
</body>
</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: