资讯专栏INFORMATION COLUMN

JavaScript...Function类型...

Eirunye / 2595人阅读

摘要:类型与函数函数是这样一段代码它只定义一次但可能被执行或调用多次类型是提供的引用类型之一通过类型创建对象在中函数也是以对象的形式存在的每个函数都是一个对象函数名本质就是一个变量名是指向某个对象的引用函数声明方式字面量方式判断函数是否为类型的中

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值作为参数 以及参数列表

// 定义函数
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可以将函数作为数据使用 作为函数本体 它像普通的数据一样 不一定要有名字 默认名字的函数被称之为匿名函数

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

回调函数

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

// 作为另一个函数(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.避免全局污染

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108223.html

相关文章

  • JS程序

    摘要:设计模式是以面向对象编程为基础的,的面向对象编程和传统的的面向对象编程有些差别,这让我一开始接触的时候感到十分痛苦,但是这只能靠自己慢慢积累慢慢思考。想继续了解设计模式必须要先搞懂面向对象编程,否则只会让你自己更痛苦。 JavaScript 中的构造函数 学习总结。知识只有分享才有存在的意义。 是时候替换你的 for 循环大法了~ 《小分享》JavaScript中数组的那些迭代方法~ ...

    melody_lql 评论0 收藏0
  • JavaScript 编写规范

    摘要:如果你想了解更多关于强制类型转换的信息,你可以读一读的这篇文章。在只使用的情况下,所带来的强制类型转换使得判断结果跟踪变得复杂,下面的例子可以看出这样的结果有多怪了明智地使用真假判断当我们在一个条件语句中使用变量或表达式时,会做真假判断。 说明 如果本文档中有任何错误的、不符合行规的,敬请斧正。 引言 不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的。...

    MartinDai 评论0 收藏0
  • javascriptfunction(){}(),new function(),new Funct

    摘要:原型之所以被称为原型,可能正是因为这种不可重载的特质。而一旦实例化,那么将指向实例化的对象。首先是,我使用了,直接利用猫咪的年龄进行计算得出体重返回给属性。 和java比起来,javascript真的是松散的无以复加,不过这也让我们在无聊之余,有精力去探讨一些复杂的应用,从而在开发之路上,获得一些新的想法。 javascript中的类的构造 javascript中有对象的概念,却没有类...

    ranwu 评论0 收藏0
  • 回家路上想起来关于Js一个有趣的东西

    摘要:忽然在下班的地铁上想起来两个的小问题,有个还和之前的吹过牛,拿出来正好说一下吧。所以我想起来之前在上不用分号的建议是值得商榷的。   最近好像有点没有之前开心,换了公司但是没有以前的活力了,好像记得之前每天上班下班都挺开心的,可能主要是之前的工作氛围真的不错吧,虽然技术真的不咋的。忽然在下班的地铁上想起来两个JavaScript的小问题,有个还和之前的leader吹过牛,拿出来正好说一...

    Sanchi 评论0 收藏0
  • 【译】stackoverflow 关于JavsScript的热门问答

    摘要:例如,考虑比较由字符串构造函数创建的字符串对象和字符串字面量这里的操作符正在检查这两个对象的值并返回,但是鉴于它们不是相同类型并且返回。我的建议是完全绕过这个问题,只是不使用字符串构造函数创建字符串对象。 Q1:javascript的闭包是如何工作的? 正如爱因斯坦所说的: 如果你不能把它解释给一个六岁的小孩,说明你对它还不够了解。 我曾尝试向一个27岁的朋友解释js闭包并且完全失败了...

    赵春朋 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<