JavaScript...Function类型...

Function类型

Function与函数

函数是这样一段JavaScript代码 它只定义一次 但可能被执行或调用屡次
Function类型是JavaScript提供的引用类型之一 经过Function类型建立Function对象
在JavaScript中 函数也是以对象的形式存在的 每一个函数都是一个Function对象
函数名 本质就是一个变量名 是指向某个Function对象的引用数组

// 1.函数声明方式
function fun(){
    console.log('this is function');
}
// 2.字面量方式
var fn = function(){
    console.log('this is function too');
}
// 判断函数是否为Function类型的
console.log(fun instanceof Function);// true
console.log(fn instanceof Function);// true
// JavaScript中全部的函数都是Function类型的对象

/*
    3.建立Function类型的对象 - 是一个函数
      var 函数名 = new Function(参数,函数体);
      * 因为函数的参数和函数体都是以字符串形式传递给Function的
  */
var f = new Function('a','console.log(a)');
f(100);// 以函数方式进行调用
  • Object与Function
// 1.Object与Function都是自身的类型
console.log(Object instanceof Object);// true
console.log(Function instanceof Function);// true
// 2.Object自身是构造函数,而构造函数也是函数,是函数都是Function类型
console.log(Object instanceof Function);// true
// 3.Function是引用类型,用于建立对象,是对象都是Object类型
console.log(Function instanceof Object);// true
  • 代码的执行流程
..变量的声明提早
console.log(v);//undefined
var v = 100;
//若是使用函数声明方式定义函数时 - 函数的声明提早
fun()
function fun(){
    console.log('this is function');
}

Function类型

  • Function的apply()方法

Function的apply()方法用于调用一个函数 而且接受指定的this值 以及一个数组做为参数缓存

// 定义函数
function fun(value){
    console.log('this is ' + value);
}
// 函数的调用方式
fun('function');// 语法结构:函数名称()
/*
    apply(thisArg,argArray)方法 -> 用于调用一个指定函数
    * 参数
      * thisArg - this
      * argArray - 数组,做为参数(实参)的列表
  */
fun.apply(null, ['function']);
  • Function的call()方法

Function的call()方法用于调用一个函数 而且接受指定的this值做为参数 以及参数列表闭包

//定义函数
function fun(value value2){
    console.log('this is' + value);
}
//函数的调用方式
fun('function','张三');//语法结构:函数名称()

fun.apply(null,['function','张三']);
//call()方法 - 用于调用一个函数
fun.call(null,'function','张三');
  • Function的bind()方法

Function的bind()方法用于建立一个新的函数(称为绑定函数) 而且接受指定的this值做为参数 以及参数列表app

// 定义函数
function fun(value){
    console.log('this is ' + value);
}
/*
    bind(thisArg, arg1, arg2, ...)方法
    * 做用 - 用于建立一个新函数(称为绑定函数)
    * 参数
      * thisArg - this
      * arg1, arg2, ... - 表示参数列表
    * 返回值 - 返回新的函数
 */
// var f = fun.bind();// 相对于从指定函数复制一份出来

fun('李四');// this is 李四

var f = fun.bind(null, '张三');
f();// this is 张三
  • 重载是什么

在其余开发语言中 函数具备一种特性 叫作重载 重载就是定义多个同名的函数 但每个函数接受的参数的个数不一样 程序会根据用时传递的实参个数进行判断 具体调用的是哪一个函数
可是在JaveScript中 函数是没有重载现象的 也就是说 若是同时定义多个同名的函数 只有最后一个定义的函数是有效的函数

/*
    重载的含义
    1.定义多个同名的函数,但具备数量不一样的参数
    2.调用函数,根据传递参数的个数调用指定的函数
 */
function add(a,b){
    return a + b;
}
function add(a,b,c){
    return a + b + c;
}
function add(a,b,c,d){
    return a + b + c + d;
}

add(1,2);// 3
add(1,2,3);// 6
add(1,2,3,4);// 10

// JavaScript的函数不存在重载 -> 当函数同名时,最后一次定义的函数有效
console.log(add(1,2));// NaN
console.log(add(1,2,3));// NaN
console.log(add(1,2,3,4));// 10
  • arguments对象

JavaScript提供了arguments对象 该对象能够模拟函数重载的现象 arguments对象是函数内部的本地变量 arguments已经再也不是函数的属性了
arguments对象能够获取函数的全部参数 但arguments对象并非一个数组 而是一个类数组对象(没有数组特有的方法)布局

/*
    JavaScript提供arguments对象
    * 该对象存储当前函数中全部的参数(实参) - 类数组对象
    * 场景 - 该对象通常用于函数中
    * 做用 - 用于获取当前函数的全部参数
    * 属性
    * length - 函数全部参数(实参)的个数
    * 用法 - 模拟实现函数的重载
 */
function add(){
    var num = arguments.length;
    switch (num) {
        case 2:
            return arguments[0] + arguments[1];
            break;
        case 3:
            return arguments[0] + arguments[1] + arguments[2];
            break;
        case 4:
            return arguments[0] + arguments[1] + arguments[2] + arguments[3];
            break;
    }
}
console.log(add(1,2));// 3
console.log(add(1,2,3));// 6
console.log(add(1,2,3,4));// 10
  • 函数的递归

调用自身的函数被称之为递归函数 在某种意义上说 递归近似于循环 二者都有重复执行相同的代码 而且二者都须要一个终止条件以免无限循环或者无限递归性能

/* 函数的递归 -> 就是在指定函数的函数体中调用自身函数
function fun(){
    // 当前函数的逻辑内容
    console.log('this is function');
    // 调用自身函数 -> 实现递归
    fun();
}
fun();
*/

function fn(v){
    console.log(v);
    if (v >= 10) {
        return;
    }
    // fn(v + 1);
    arguments.callee(v + 1);
}
// fn(0);

var f = fn;
fn = null;
f(0);
// console.log(f);

特殊函数

  • 匿名函数

JavaScript能够将函数做为数据使用 做为函数本体 它像普通的数据同样 不必定要有名字 默认名字的函数被称之为匿名函数this

function(a){return a;}
/*
    匿名函数的做用:
    1.将匿名函数做为参数传递给其余函数 - 回调函数
    2.将匿名函数用于执行一次性任务 - 自调函数
 */
  • 回调函数

当一个函数做为参数传递给另外一个函数时 做为参数的函数被称之为回调函数code

// 做为另外一个函数(fn)的参数的函数(one) - 回调函数
var one = function(){
    return 1;
}

function fn(v){
    return v();
}
// one函数仅是做为fn函数的参数出现 - 并非调用
// var result = fn(one);
/*
    以上代码等价于如下代码
    如下代码中做为参数的函数 - 匿名回调函数
  */
var result = fn(function(){return 1;});

console.log(result);// 1

回调函数的优势:
1.它能够在不作命名的的状况下传递函数(这意味着能够节省全局变量)
2.能够将一个函数调用操做委托给另外一个函数(这意味着能够节省一些代码编写工做)
3.回调函数也有助于提高性能对象

  • 回调函数的参数
// 做为另外一个函数(fn)的参数的函数(one) -> 回调函数
var one = function(w){
    return w;
}

function fn(v){// 形参是一个函数
    return v(100);// 函数的调用体
}

// var result = fn(one);// 实参必须是一个函数

var result = fn(function(w){return w;});

console.log(result);
  • 自调函数

自调函数就是定义函数后自行调用

/*
    自调函数 - 定义即调用的函数
    * 第一个小括号 - 用于定义函数
    * 第二个小括号 - 用于调用函数
 */
// 全局做用域 - 生命周期:JavaScript文件从执行到执行完毕
(function(value){
    // 函数做用域 - 生命周期:从函数调用到调用完毕
    console.log('this is ' + value);
})('function');
// 表达式语法
(function(value){
    // 函数做用域 - 生命周期:从函数调用到调用完毕
    console.log('this is ' + value);
}('function'));

!function(value){
    // 函数做用域 - 生命周期:从函数调用到调用完毕
    console.log('this is ' + value);
}('function');

+function(value){
    // 函数做用域 - 生命周期:从函数调用到调用完毕
    console.log('this is ' + value);
}('function');
  • 做为值的函数

将一个函数做为另外一个函数的结果进行返回 做为结果返回的函数称之为值的函数

var one = function(){
    return 100;
}
// 做为值的函数 -> 内部函数的一种特殊用法
function fun(){
    var v = 100;
    // 内部函数
    return function(){
        return v;
    };
}

var result = fun();
//console.log(result);// one函数
//console.log(result());// 100

console.log(fun()());

闭包

  • 做用域链

不少开发语言中都具备块级做用域 但ECMAScript5版本中并无跨级做用域 这常常会致使理解上的困惑
虽然ECMAScript5版本没有块级做用域 但具备函数做用域 在某个函数内部定义的便利的做用域就是该函数做用域
每一段JavaScript代码(全局代码或函数)都有一个与之关联的做用域链

var a = 10;// 全局变量
function fun(){
    var b = 100;// fun函数做用域的局部变量
    // 内部函数
    function fn(){
        var c = 200;// fn函数做用域的局部变量
        // 内部函数
        function f(){
            var d = 300;// f函数做用域的布局变量
            // 调用变量
            console.log(a);// 10
            console.log(b);// 100
            console.log(c);// 200
            console.log(d);// 300
        }
        f();
        // 调用变量
        // console.log(a);// 10
        // console.log(b);// 100
        // console.log(c);// 200
        // console.log(d);// d is not defined
    }
    fn();
    // 调用变量
    // console.log(a);// 10
    // console.log(b);// 100
    // console.log(c);// c is not defined
    // console.log(d);// d is not defined
}
fun();
  • 闭包

JavaScript容许函数嵌套 而且内部函数能够访问定义在外部函数中的全部变量和函数 以及外部函数能访问的全部变量和函数 可是 外部函数却不可以访问定义在内部函数中的变量和函数
当内部函数以某一种方式被任何一个外部函数做用域访问时 一个闭包距产生了
闭包就是词法表示包括没必要计算的变量的函数 也就是说 该函数能使用函数外定义的变量

var n;// 定义变量,但不初始化值
function fun(){// 函数做用域
    var v = 100;
    // 进行初始化值 -> 一个函数
    n = function(){
        console.log(v);
    }
    // n();
}
fun();

n();// 100
  • 闭包的特色与做用

闭包的特色:1.局部变量:在函数中定义有共享意义(如 缓存 计数器等)的局部变量(注:定义全局变量会对外形成污染)2.内部函数:在函数(f)中声明有内嵌函数 内嵌函数(g)对函数(f)长得局部变量进行访问3.外部使用:函数(f)向外返回此内嵌函数(g) 外部能够经过此内嵌函数持有并访问声明在函数(f)中的变量 而此变量在外部是经过其余途径没法访问的闭包的做用:1.提供可共享的局部变量2.保护共享的局部变量 提供专门的读写变量的函数3.避免全局污染

相关文章
相关标签/搜索