一、 Function类型
函数实际上是对象。每个函数都是Function类型都实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象都指针。
1、函数通常是使用函数声明语法定义的

  1. function sum(num1,num2){
  2. return num1+num2
  3. }

2、这与下面使用函数表达式定义的方式几乎相差无几

  1. var sum = function(num1,num2){
  2. return num1 + num2
  3. }

3、最后一种定义函数的方式是使用Function构造函数,它可以接收任意数量的参数,但最后一个参数始终都被看成函数体

  1. var sum = new Function('num1','num2','return num1+num2');//不推荐

由于函数名仅仅是指向函数都指针,因此函数名与包含对象指针的其他变量没有什么不同。

  1. function sum(num1,num2){
  2. return num1+num2;
  3. }
  4. console.log(sum(10,10)); //
  5.  
  6. var anotherSum = sum;
  7. console.log(anotherSum(10,10)); //
  8.  
  9. sum = null;
  10. console.log(anotherSum(10,10));//

二、没有重载
1、将函数名想象为指针,有助于理解为什么es(ECMAScript)中没有函数重载的概念

  1. function addSomeNum(num){
  2. return num + 100;
  3. }
  4. function addSomeNum(num){
  5. return num + 200;
  6. }
  7. var result = addSomeNum(100);
  8. console.log(result); //

转化一下

  1. var addSomeNum = function(num){
  2. return num + 100;
  3. }
  4. addSomeNum = function(num){
  5. return num + 200;
  6. }
  7. var result = addSomeNum(100);

通过观察重写之后的代码,很容易看清楚到底是怎么回事儿,在创建第二个函数时,实际上覆盖了引用第一个函数的变量addSomeNum

三、函数声明和函数表达式的区别

  1. console.log(sum(10,10));
  2. function sum(num1,num2){
  3. return num1 + num2;
  4. }

可以正常运行

  1. console.log(sum1(10,10));
  2. var sum1 = function(num1,num2){
  3. return num1+num2;
  4. }

不能正常运行

因为解析器通过一个名为函数声明提升的过程,读取并将函数声明添加到执行环境中。函数表达式只提升变量sum,变量sum中还没有函数的引用,除了这点区别外,
函数声明与函数表达式的语法其实是等价的

四、函数里面的参数是一个函数时
传入一个函数时

  1. function callSomeFunction(someFunction,somArgument){
  2. return someFunction(somArgument);
  3. }
  4. function add10(num){
  5. return num + 10;
  6. }
  7. var result1 = callSomeFunction(add10,10);
  8. console.log(result1); //
  9.  
  10. function getGreeting(name){
  11. return 'hello,' + name;
  12. }
  13. var result2 = callSomeFunction(getGreeting,'Lucy');
  14. console.log(result2); //'hello,Lucy'

这里的callSomeFunction()是通用的

返回一个函数时
这里是一个对象数组,我们想要根据某个属性对数组进行排序,而传递给数组sort()方法对比较函数要接收两个参数,ap即要比较的值。可是,我们需要一种中方式来指明按照哪个属性来排序,要解决这个问题

  1. function creatComparisonFuntion(propertyName){
  2. return function(object1,object2){
  3. var value1 = object1[propertyName];
  4. var value2 = object2[propertyName];
  5. if(value1 < value2){
  6. return -1;
  7. }else if( value1 > value2){
  8. return 1;
  9. }else{
  10. return 0
  11. }
  12. }
  13. }
  14. var data=[{name:'Lily',age:29},{name:'Lucy',age:39},{name:'Jone',age:19},{name:'Han',age:49},{name:'Ming',age:9}];
  15. data.sort(creatComparisonFuntion('name'));
  16. console.log(data);
  17. data.sort(creatComparisonFuntion('age'));
  18. console.log(data)

从一个函数中返回另一个函数,这也是极为有用的一种技术,上面这样返回函数形式可以解决

五、arguments和this (函数内部属性)
1、arguments是一个类数组对象,包含着传入函数中到所有参数。虽然arguments到主要用途是保存函数参数。
但这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
经典的阶乘函数

  1. function factorial(num){
  2. if(num<1){
  3. return 1;
  4. }else{
  5. return num * factorial(num - 1)
  6. }
  7. }

定义阶乘函数一般都要用到递归函数:在函数有名字,而且名字以后也不会变的情况下,这样定义没有问题。但问题是这个函数与函数名factorial紧紧耦合在了一起。
为了消除这种紧密耦合的想象,可以像下面这样使用arguments.callee.

  1. function factorial(num){
  2. if(num<1){
  3. return 1;
  4. }else{
  5. return num * arguments.callee(num - 1);
  6. }
  7. }

重写后的函数体内,没有再引用函数名factorial,这样,无论引用函数时使用的是什么名字,都可以保证正常名字完成递归调用

  1. var trueFactorial = factorial;
  2. factorial = function(){
  3. return 0;
  4. }
  5. alert(trueFactorial(5)); //
  6. alert(factorial(5)); //

六、函数都属性和方法
属性:length和prototype
方法:call,apply,bind
1、length:表示函数希望接收都命名参数都个数

  1. function sum(num1,num2){
  2. return num1+num2
  3. }
  4. console.log(sum.length) //

2、prototype:保存它们所有实例方法都真正所在,prototype属性不可枚举,因此使用for-in无法实现
3、apply()和call()用途都是在特定的作用域中调用函数
apply()接收两个参数,一个是在其中运行函数的作用域,另一个是参数数组

  1. function sum(num1,num2){
  2. return num1 + num2;
  3. }
  4. function callSum1(num1,num2){
  5. return sum.apply(this,arguments); //传入arguments对象
  6. }
  7. function callSum2(num1,num2){
  8. return sum.apply(this,[num1,num2]); //传入数组
  9. }
  10. console.log(callSum1(10,10)); //
  11. console.log(callSum2(10,10)); //

这里面的this值因为是在全局作用域中调用的,所以传入的就是window对象

  1. function sum(num1,num2){
  2. return num1 + num2;
  3. }
  4. function callSum(num1,num2){
  5. return sum.call(this,num1,num2);
  6. }
  7. console.log(callSum(10,10));//

使用apply()还是call(),完全取决于你采用哪种给函数传递参数的方式最方便。

事实上,传递参数并非apply()和call()真正的用武之地;它们真正强大的地方是能够扩充函数赖以运行的作用域

  1. window.color = 'red';
  2. var o = {color:'blue'};
  3. function sayColor(){
  4. console.log(this.color);
  5. }
  6. console.log(sayColor()); //red
  7. console.log(sayColor.call(this)); //red
  8. console.log(sayColor.call(window)); //red
  9. console.log(sayColor.call(o)); //blue

使用call()或者apply()来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系
4、bind()会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

  1. window.color = 'red';
  2. var o = {color:'blue'};
  3.  
  4. function sayColor(){
  5. console.log(this.color);
  6. }
  7.  
  8. var objectSayColor = sayColor.bind(o);
  9. objectSayColor(); //blue

在这里,sayColor()调用bind()并传入对象o,创建了 objectSayColor()函数,objectSayColor()函数的this值等于o,
因此即使是在全局作用域中调用这个函数,也会看到'blue'

引用类型(三):Function类型的更多相关文章

  1. 引用类型之Function类型

    Function类型 ECMAScript中最有意思的就是函数了,有意思的根源,在于函数实际上是对象.每个函数都是Function的实例,具有属性和方法.而重要的一点是,函数名,不过是指向函数的指针, ...

  2. 小红书第五章——引用类型之function类型

    有趣的函数——function类型 函数实际上是对象,每个函数都是function类型的实例,具有属性和方法. 1.函数的定义方法 1)函数声明语法 function sum(num1,num2){/ ...

  3. 引用类型-Function类型

    Function类型 定义函数的三种方式: 1.函数声明 function sum(num1,num2){ return num1 +num2; } 2.函数表达式 var sum = functio ...

  4. Javascript高级编程学习笔记(16)—— 引用类型(5) Function类型

    JS中许多有趣的地方都和函数脱不了联系 那么是什么让JS中的函数这么有趣呢? 我们一起来看看吧 Function类型 在JS中函数实际上就是对象,每个函数都是Function类型的实例,和JS的其他引 ...

  5. 引用类型--Function类型(函数声明与函数表达式、arguments.callee、caller、apply、call、bind)

    在ECMAScript中函数实际上是对象.每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定 ...

  6. JavaScript笔记——引用类型之Object类型和Function类型

    <JavaScript高级程序设计>中介绍的几种JavaScript的引用类型,本文只记了Object跟Function类型 Object类型 创建对象 var person = new ...

  7. CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段

    编程语言的基元类型   某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32();  // a = 0 a = 1 ...

  8. CLR via #C读书笔记三:基元类型、引用类型和值类型

    1.一些开发人员说应用程序在32位操作系统上运行,int代表32位整数:在64位操作系统上运行,int代表64位整数.这个说法是完全错误的.C#的int始终映射到System.Int32,所以不管在什 ...

  9. C#篇(三)——函数传参之引用类型和值类型

    首先应该认清楚在C#中只有两种类型: 1.引用类型(任何称为"类"的类型) 2.值类型(结构或枚举) 先来认识一下引用类型和值类型的区别: 函数传参之引用类型: 1.先来一个简单的 ...

随机推荐

  1. 1 Groovy

    1.1  什么是Groovy? groovy 是一个弱类型,动态语言,并且运行在JVM之上.它与java联系紧密.它是一个功能丰富和友好的java语言. Groovy源代码,通过Groovy编译器编译 ...

  2. Netcore中实现字段和属性注入

    https://www.cnblogs.com/loogn/p/10566510.html 简单来说,使用Ioc模式需要两个步骤,第一是把服务注册到容器中,第二是从容器中获取服务,我们一个一个讨论并演 ...

  3. 1.1 Rust安装

    从今天起,坚持每天学习10分钟Rust...这是一个刚兴起几年的语言,希望深入地进行学习,为什么呢,因为以下这些让人辛酸的理由..... 最开始学习的是C++,没学太懂,之后又学了C,这时还完全对计算 ...

  4. [引]雅虎日历控件 Example: Two-Pane Calendar with Custom Rendering and Multiple Selection

    本文转自:http://yuilibrary.com/yui/docs/calendar/calendar-multipane.html This example demonstrates how t ...

  5. OpenStack Weekly Rank 2015.08.24

    Module Reviews Drafted Blueprints Completed Blueprints Filed Bugs Resolved Bugs Cinder 5 1 1 6 13 Sw ...

  6. PHP post & get请求

    <?php /** * HTTP 请求类 */ class HttpHelper { const METHOD_GET = 'GET'; const METHOD_POST = 'POST'; ...

  7. accecc2010入门,语文

    accecc2010入门 数据库:存放数据并处理的仓库. access2010数据库(扩展名为accdb,改名时不能删扩展名): 1,功能区:代替了菜单栏和工具栏的功能,不用四处查找命令.在窗口下的顶 ...

  8. intellijidea课程 intellijidea神器使用技巧2-1 无处不在的跳转

    idea快捷键(基于windows平台) 1 书签跳转 Ctrl alt [ ]   ==> 项目之间的跳转 Ctrl shift E ==> 文件之间的跳转(最近编辑的文件) Ctrl ...

  9. cf914F. Substrings in a String(bitset 字符串匹配)

    题意 题目链接 Sol Orz jry 和上一个题一个思路吧,直接bitset乱搞,不同的是这次有了修改操作 因为每次修改只会改两个位置,直接暴力改就好了 #include<bits/stdc+ ...

  10. DOM 事件冒泡

    1.什么是事件冒泡? 事件冒泡就是从具体到不具体, 例如:当你给了一个button按钮一个点击事件,再给他的父级相同的事件,就会按照,button,body,document,window,继续向上冒 ...