2016年4月20日
[TOC]
2016年4月20日
javascript
apply()与call()
函数属性的继承与传递
/*定义一个人类*/
function Person(name,age)
{
this.name=name;
this.age=age;
}
/*定义一个学生类*/
function Student(name,age,grade)
{
Person.apply(this,arguments);
this.grade=grade;
}
//创建一个学生类
var student=new Student("qian",21,"一年级");
//测试
alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);
//大家可以看到测试结果name:qian age:21 grade:一年级
//学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢,这个就是apply的神奇之处.Function.apply(obj,args)方法能接收两个参数 obj:这个对象将代替Function类里this对象,将调用函数Person里的this变成函数Student的this。 args:这个是数组,它将作为参数传给Function(args-->arguments)
在Studen函数里面可以将apply中修改成如下:
Person.call(this,name,age);
函数的声明
function命令
上面的代码命名了一个print函数,以后使用print()这种形式,就可以调用相应的代码。这叫做函数的声明(Function Declaration)。
函数表达式
这种写法将一个匿名函数赋值给变量。这时,这个匿名函数又称函数表达式(Function Expression),因为赋值语句的等号右侧只能放表达式。
采用函数表达式声明函数时,function命令后面不带有函数名。如果加上函数名,该函数名只在函数体内部有效,在函数体外部无效。
Function构造函数
在上面代码中,Function构造函数接受三个参数,除了最后一个参数是add函数的“函数体”,其他参数都是add函数的参数。
函数内部的变量提升
var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。
上面的代码等同于
函数本身的作用域
函数本身也是一个值,也有自己的作用域。它的作用域绑定其声明时所在的作用域。
函数x是在函数f的外部声明的,所以它的作用域绑定外层,内部变量a不会到函数f体内取值,所以输出1,而不是2。
函数值传递方式
函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。这意味着,在函数体内修改参数值,不会影响到函数外部。
如果函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。
如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。
如果需要对某个原始类型的变量,获取传址传递的效果,可以将它写成全局对象的属性。
arguments对象
虽然arguments很像数组,但它是一个对象。
下面是两种常用的转换方法:slice方法和逐一填入新数组。
callee属性
arguments对象带有一个callee属性,返回它所对应的原函数。
闭包
函数内的函数。
JavaScript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。
闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。
外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。
立即调用的函数表达式(IIFE)
让引擎知道,圆括号前面的部分不是函数定义语句,而是一个表达式,这样就可以对此进行运算。
一是不必为函数命名,避免了污染全局变量;二是IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。
eval命令
eval命令的作用是,将字符串当作语句执行。
Last updated
Was this helpful?