什么是函数?

引用 W3School 的原话:函数是一组可以随时随地运行的语句。
函数是 ECMAScript 的核心。
函数是由这样的方式进行声明的:关键字 function、函数名、一组参数,以及置于括号中的待执行代码。
函数的基本语法是这样的:
function functionName(arg0, arg1, ... argN) {statements
}
  1. 声明函数的几种方式

  2. 调用函数的几种方式

  3. 重载函数的实现

  4. 函数的独立性

声明函数

//声明函数的4种方法//方法一 直接声明
function speak(word){console.log(word)
}//方法二 指定一个匿名函数 将其赋给一个变量,后面可以直接通过该变量调用该函数
var speak2 = function (word) {console.log(word);
};//定义匿名函数需要注意最后需要加分号//方法三 使用 Function对象 生成一个函数实例
var speak3 = new Function("word","console.log(word);");//方法四 使用 Function函数 返回函数实例
var speak4 = Function("word","console.log(word);");

调用函数基本方法

speak("hello world for global !");this.speak("hello world for this !");window.speak("hello world for window !");

调用函数的高级方法

speak.call(null,"hello world with call !");//null 代表是用全局对象 window 调用speak.apply(null,["hello world with apply !"]);

输出结果:

这里方法一大家不言而喻,简单明了,直接就是声明了一个函数,需要指出的是,默认写的函数在不依附其他对象的情况下均为全局函数,即成为 window 对象的成员,可以直接使用 window(Window 对象的实例,Window 对象实现了核心 JavaScript 所定义的所有全局属性和方法)调用,或者通过 this 调用,在这里JS 顶层代码中 this 指向的就是 window

每当我们使用方法一声明了一个函数的时候,实际是生成了一个 Function 对象的实例.即每个函数其实质都是一个 Function 对象实例.

注意:
JS 解析器每解析到一个函数的时候,都会在堆内存内划分出一块空间来存储创建该 Function 实例

方法二:
首先 JS 解析器解析到一个函数的时候,在堆内存内划分出一块空间来存储创建该 Function 实例,接着在当前栈内存
创建一个叫 speak2 的变量,这个变量有个值,这个值是一个地址,指向的是堆内存中的那个 Function 实例.实际上这就是大名鼎鼎的引用.

方法三:
与方法一和方法二不同的是,前两个方法都是声明好让解析器去解析,让解析器生成 Function 实例(就是上面声明的函数,解析器调用 Function 构造器来生成实例,这些步骤是我们看不到的),方法三是我们手动调用 Function 构造器生成 Function 实例(步骤掌握在自己的手里)

方法四:
与方法三不同的地方就是没有 new,在这里 new 与没 new 的区别就是当有 new 的时候 Function 函数充当一个构造器,new 后返回的就是实例化后得到的对象(此时Function 内部的 this指向的就是当前生成的对象),不使用 new 的话就是把 Function 函数看做一个普通函数直接调用,直接调用 Function 函数让其在内部(我们看不到)new 一个实例返回,本质是一样的.

call方法与 apply 方法
查看EcmaScript.js

可以看到 call 方法与 apply 方法的区别:

  • 他们的第一个参数指的是调用该方法对象

  • call 方法的第二个参数是可变数组参数,即可以传入多个参数,非传入一个数组.传入的多个参数对应的是被调用方法的各参数.

  • apply 方法的第二个参数是一个数组对象,即可以直接传入一个数组对象,数组对象的每项对应的是被调用的方法的各参数.

实现重载函数
在 JS 中,并不像其他强类型语言一样可以声明重载函数,若在原先声明的函数后再声明一个不同参数数量的函数(JS是弱语言, 声明的函数不需要指明参数类型),解析器会用后面声明的函数覆盖前面声明的函数.那我们该如何实现呢.

arguments 对象
在每个函数都有一个arguments 属性,同样查看 EcmaScript.js

当生成一个函数实例后,解析器会赋给arguments 属性一个Arguments对象实例,这个实例是什么,再看 EcmaScript.js

可以得知其为一个对象同时为数组对象的子类,故可以将其当初数组对象使用.
函数实例中的 arguments对象(可以算是一个数组)的数组项内容便是我们在调用函数时进行传递的参数.只要我们有传参,这个属性就有数组项,否则数组长度为0,故我们可以通过arguments.length 来查看其得到的形参的数量.

有了上面的基础便可实现重载函数
这里引用 W3School 的例子

function doAdd() {if(arguments.length == 1) {alert(arguments[0] + 5);} else if(arguments.length == 2) {alert(arguments[0] + arguments[1]);}
}doAdd(10);        //输出 "15"
doAdd(40, 20);    //输出 "60"

函数的独立性
我们都知道,每当我们声明了一个函数,其实际为一个 Function 实例,那它独立在哪呢,如何体现呢
看一下代码:

function Dog(name,age){this.name = name;this.age = age;this.showName = function () {console.log(this.name);}
}function Cat(name,age){this.name = name;this.age = age;this.showName = function () {console.log(this.name);}
}var dog = new Dog("wangwang",2);
var cat = new Cat("miaomiao",3);dog.showName();
cat.showName();
dog.showName.call(cat);

输出结果为:

解释:
每当我们在函数内使用 this 的时候,无非这几种情况:
1.作为构造器生成的实例对象
2.作为调用当前方法的对象
3.在 JS 顶层代码可以使用 this 代表 window 调用全局函数等

故当我们使用 call 方法调用某个对象的方法时,虽然从代码语义上看,这个所属方法是属于该对象的(showName 属于 Dog 或 Cat),但是由于函数有用其特殊的独立性即有以上几个关于 this 的特点,导致最终的结果是不同的.
当我们直接调用 dog 的 showName 方法时,showName 方法内的 this 指向的是该dog 对象(Dog 实例).

我们知道调用 call 方法时需要传入的第一个参数即为调用当前函数亦或方法的对象,此时被调用的方法的 this 指向的实际为传入的第一个参数.即当我们通过 call 调通 dog 的 showName 方法时,传入的第一个参数是 cat 对象,代表 dog 的 showName 方法的 this 此时指向的不是 dog 是 cat.最后输出的当然是 cat 的内容

最后指出:在对函数进行传参时,若传的是 JS 的基本类型,则为值传递,否则为引用传递.

浅谈细说 JS 函数(call,apply,重载)相关推荐

  1. python中怎么调用函数_浅谈Python中函数的定义及其调用方法

    一.函数的定义及其应用 所谓函数,就是把具有独立功能的代码块组织成为一个小模块,在需要的时候调用函数的使用包含两个步骤 1.定义函数–封装独立的功能 2.调用函数–享受封装的成果 函数的作用:在开发时 ...

  2. 浅谈Vue.js的优势

    写在前面 今天小梦跟小伙伴们简简单单聊一下Vue.js的优势.小梦也是刚刚接触Vue.js,在学习一门新的技术之前,我们当然要了解其优势,知道优势在哪更加有利于我们去学习并转换为自己的储备. 浅谈Vu ...

  3. ajax参数中有加号,浅谈在js传递参数中含加号(+)的处理方式

    一般情况下,URL 中的参数应使用 url 编码规则,即把参数字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+). 但是对于带有中文的参数 ...

  4. python函数定义及调用-浅谈Python中函数的定义及其调用方法

    一.函数的定义及其应用 所谓函数,就是把具有独立功能的代码块组织成为一个小模块,在需要的时候调用函数的使用包含两个步骤 1.定义函数�C封装独立的功能 2.调用函数�C享受封装的成果 函数的作用:在开 ...

  5. 【浅谈】main函数的三个参数

    [浅谈]main函数的参数 我们平时使用main函数时,在main函数参数这一栏常常省略不写,或者填上(void).实际上main函数是具有参数的,并且它的参数有很大作用.今天我们来看看main函数的 ...

  6. 浅谈C++的函数重载

    转自:微点阅读(www.weidianyuedu.com)微点阅读 - 范文大全 - 免费学习网站 导语: 函数重载的重要性不言而明,但是你知道C++中函数重载是如何实现的呢(虽然本文谈的是C++中函 ...

  7. 浅谈Node.js(概念、安装、入门例子)

    2019独角兽企业重金招聘Python工程师标准>>> 1.Node.js是什么? 你可以认为它是一个全新的语言,可以用于编写WEB服务端程序或独立的运行进程.但是呢,为了减少你学习 ...

  8. 浅谈一下js中的this

    1. 对this对象的理解:this 是执行上下文中的一个属性,它指向最后一次调用这个方法的对象. * 任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是window * 所有函数内部都有一 ...

  9. 浅谈对js闭包的理解

    闭包就是能够读取其他函数内部变量的函数.由于在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成"定义在一个函数内部的函数".在本质上,闭包是将函数内 ...

最新文章

  1. HTML怎么编写可关闭广告,JS实现关闭小广告特效
  2. 人工智能可以自己编码?2022年这8个人工智能趋势值得关注!
  3. 图解wordpress3.5.1最简单实现伪静态的方法
  4. 12.10 Nginx访问日志 12.11 Nginx日志切割 12.12 静态文件不记录日志和过期时间
  5. Googlenet笔记
  6. 调用ice服务器_Nodejs+socket.io搭建WebRTC信令服务器
  7. informix mysql,Informix相当于mysql的SHOW CREATE TABLE
  8. oracle Expdp带条件,Oracle 11g expdp中query参数的使用
  9. c语言怎样设计程序界面,「分享」C语言如何编写图形界面
  10. 2021年7月国产数据库大事记
  11. 90后绝对不是用来管的!
  12. 升级工作环境并支持C++17
  13. JavaWeb-JSON
  14. Python(3)——Python基本图形绘制
  15. 自制随机小姐姐摄影api
  16. PICT测试工具的安装及使用
  17. Python 员工工时汇总
  18. OA系统十七:请假申请三:【请假申请】这个内嵌界面中【提交请假表单数据】的Service层;(PS:在EmployeeDao中初次遇到@Param()参数设置)
  19. Unix、x86左右互搏 惠普“龙跃”乃“缓兵之计”?
  20. JAVA使用Springboot+MP+VUE+Swagger前后端分离进行微信支付

热门文章

  1. matplotlib画图_Python数据可视化工具Matplotlib之画图(四)(饼状图)
  2. fanuc机器人码垛编程实例_两个很简单的FANUC系统CNC加工中心编程实例
  3. 在线html编辑器 asp,(ewebeditor)比较简单好用的ASP网页在线编辑器
  4. html表单的课后心得体会,web前端学习心得体会范文
  5. gcc可以编译python程序吗_GCC编译C语言程序完整演示
  6. Maven项目有红叉,文件却没有错误,已解决
  7. html5的service worker,GitHub - w3c/ServiceWorker: Service Workers
  8. spss多元线性回归散点图_案例分析 | 多元线性回归及SPSS操作
  9. php1500,圆周率1500多位
  10. android SDK安装以及环境变量配置