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变成函数Studentthisargs:这个是数组,它将作为参数传给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?