资讯专栏INFORMATION COLUMN

JavaScript面向对象编程——Function类型

Object / 3293人阅读

摘要:在中,函数也是以对象的形式存在的。也可以使用对象作为参数返回值调用该函数的返回结果。调用自身的函数被称之为递归函数。默认名字的函数被称之为匿名函数。内部函数在函数中声明内嵌函数,内嵌函数对函数中的局部变量进行访问。

Function类型 Function与函数

函数它只定义一次,但可能被执行或调用多次 。
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);// 以函数方式进行调用
Function类型 构造函数

在JavaScript中,函数除了可以通过函数定义语句或字面量表达式两种方式定义之外,还可以通过Function类型进行定义。(注意:通过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");
}
apply()方法

Function的apply()方法用于调用一个函数,并且接受指定的this值,以及一个数组作为参数。
语法结构:
1.thisArg参数:可选项,在func函数运行时使用this值。
2.argsArray参数:可选项,一个数组或者类数组对象,其中你那个的数组元素将作为多带带的参数传给func函数。也可以使用argments对象作为参数
3.返回值:调用该函数的返回结果。

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

    apply(thisArg,argArray)方法 -> 用于调用一个指定函数
     参数
       thisArg - this
       argArray - 数组,作为参数(实参)的列表
  
fun.apply(null, ["function"]);
call()方法

Function的call()方法用于调用一个函数,并且接收指定的this值作为参数,以及参数列表。
语法结构:
1.thisArg参数:在func函数运行时使用的this值。
2.arg1,arg2,...参数:指定的参数列表。
3.返回值:调用该函数的返回结果。
apply()与call()非常相似,不同之处在于提供参数的方式。

bind()方法

Function的bind()方法用于创建一个新的函数(称之为绑定函数),并且接收指定的this值作为参数,以及参数列表。

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

fun("周芷若");// this is 周芷若

var f = fun.bind(null, "张无忌");
f();// this is 张无忌
没有重载

在其他开发语言中,函数具有一种特性,叫做重载。所谓的重载,就是定义多个同名的函数,但每一个函数接收的参数的个数不同,程序会根据调用是传递的实参个数进行判断,具体调用的是哪个函数。

// 定义函数
function fun(value){
    console.log("this is " + value);
}

    bind(thisArg, arg1, arg2, ...)方法
     作用 - 用于创建一个新函数(称为绑定函数)
     参数
       thisArg - this
       arg1, arg2, ... - 表示参数列表
     返回值 - 返回新的函数
 
 var f = fun.bind();// 相对于从指定函数复制一份出来
 console.log(f);
 f();

fun("周芷若");// this is 周芷若

var f = fun.bind(null, "张无忌");
f();// this is 张无忌

但在JavaScript中函数时没有重载现象的。也就是说,如果同时定义多个同名函数,只有最后一个定义的函数时有效的。
不过,JavaScript提供的arguments对象,该对象可以模拟函数重载的现象。arguments对象是函数内部的本地变量;arguments已经不再是函数的属性了。
arguments对象可以获取函数的所有参数,但arguments对象并不是一个数组,而是一个类数组对象(没有数组特有的方法)。

递归

在一个函数体内,如果想调用自身函数的话,有两种方式;
1.通过使用自身函数实现
2.通过使用arguments对象的callee属性实现。
调用自身的函数被称之为递归函数。在某种意义上,递归近似于循环。两者都重复执行相同的代码,并且两者都需要一个终止条件以避免无限循环或者无限递归。

/* 函数的递归 -> 就是在指定函数的函数体中调用自身函数
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可以将函数作为数据使用。作为函数本体,他就像普通的数据一样,不一定要有名字。默认名字的函数被称之为匿名函数。
匿名函数的两种用法:
1.可以将匿名函数作为从参数传递给其他函数。这样,接收函数就能利用所传递的函数来完成某些事请。
2.可以定义某个匿名函数来执行某些一次性任务。

 JavaScript语法中,定义函数必须定义函数名称 -> 匿名函数
function (){
    console.log("this is function");
}


    匿名函数的作用:
    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.第二个对括号的作用,是‘立即调用’。在调用时,向匿名函数传递参数内内容。
自调函数只需将匿名函数的定义放进一对括号中,然后外面在跟一个对括号。

    自调函数 - 定义即调用的函数
     第一个小括号 - 用于定义函数
     第二个小括号 - 用于调用函数
 
// 全局作用域 - 生命周期: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/108228.html

相关文章

  • JavaScript设计模式与开发实践 | 01 - 面向对象JavaScript

    摘要:在中,并没有对抽象类和接口的支持。例如,当对象需要对象的能力时,可以有选择地把对象的构造器的原型指向对象,从而达到继承的效果。本节内容为设计模式与开发实践第一章笔记。 动态类型语言 编程语言按数据类型大体可以分为两类:静态类型语言与动态类型语言。 静态类型语言在编译时已确定变量类型,动态类型语言的变量类型要到程序运行时,待变量被赋值后,才具有某种类型。 而JavaScript是一门典型...

    suxier 评论0 收藏0
  • 面向对象JavaScript(如何一步步成为js高手)

    摘要:虽然,也是面向疾苦的语言,但是,它和静态类型语言的面向接口编程不一而足。对象对他自己的行为负责,其他对象不关心它的内部实现。 ‘工欲善其事,必先利其器’,在深入学习JavaScript之前,我认为我们很有必要了解以下,JavaScript这门面向对象的动态语言到底是一门什么样的语言。 JavaScript vs 其他面向对象语言 它没有使用像Java等传统的面向对象语言的类式继承,而...

    peixn 评论0 收藏0
  • JavaScript面向对象编程-封装

    摘要:前言面向对象编程是将需求抽象成一个对象,针对对象分析其特征属性和动作方法。面向对象编程思想其中一个特点就是封装,就是把需要的功能放在一个对象里。将闭包作为创建对象的构造函数。 前言 面向对象编程是将需求抽象成一个对象,针对对象分析其特征(属性)和动作(方法)。这个对象我们称之为类。面向对象编程思想其中一个特点就是封装,就是把需要的功能放在一个对象里。但是JavaScript这种解释性的...

    taoszu 评论0 收藏0
  • JS程序

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

    melody_lql 评论0 收藏0
  • JavaScript中的面向对象(object-oriented)编程

    摘要:对象在中,除了数字字符串布尔值这几个简单类型外,其他的都是对象。那么在函数对象中,这两个属性的有什么区别呢表示该函数对象的原型表示使用来执行该函数时这种函数一般成为构造函数,后面会讲解,新创建的对象的原型。这时的函数通常称为构造函数。。 本文原发于我的个人博客,经多次修改后发到sf上。本文仍在不断修改中,最新版请访问个人博客。 最近工作一直在用nodejs做开发,有了nodejs,...

    JerryZou 评论0 收藏0
  • JavaScript面向对象编程简明教程

    摘要:这样每个实例独享自己的属性,并和其他同类型的实例共享方法构造函数原型以上这种方式定义的类型,可以通过来判断一个实例是否是类型的实际上是通过实例的原型链来判断一个对象是否某个类型的实例的,具体的细节后面会详细介绍。 JavaScript面向对象编程 如何定义自定义类型 首先需要明确,JavaScript并不是传统意义上的OO语言,它并没有class的概念, 而是包含了另一套异常强大的...

    myeveryheart 评论0 收藏0

发表评论

0条评论

Object

|高级讲师

TA的文章

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