引用类型(三):Function类型

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

function sum(num1,num2){
    return num1+num2
}

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

var sum = function(num1,num2){
    return num1 + num2
}

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

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

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

function sum(num1,num2){
    return num1+num2;
}
console.log(sum(10,10)); //20

var anotherSum = sum;
console.log(anotherSum(10,10)); //20

sum = null;
console.log(anotherSum(10,10));//20

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

function addSomeNum(num){
    return num + 100;
}
function addSomeNum(num){
    return num + 200;
}
var result = addSomeNum(100);
console.log(result); //300

转化一下

var addSomeNum = function(num){
    return num + 100;
}
addSomeNum = function(num){
    return num + 200;
}
var result = addSomeNum(100);

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

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

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

可以正常运行

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

不能正常运行

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

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

function callSomeFunction(someFunction,somArgument){
    return someFunction(somArgument);
}
function add10(num){
    return num + 10;
}
var result1 = callSomeFunction(add10,10);
console.log(result1); //20

function getGreeting(name){
    return ‘hello,‘ + name;
}
var result2 = callSomeFunction(getGreeting,‘Lucy‘);
console.log(result2); //‘hello,Lucy‘

这里的callSomeFunction()是通用的

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

function creatComparisonFuntion(propertyName){
    return function(object1,object2){
        var value1 = object1[propertyName];
        var value2 = object2[propertyName];
        if(value1 < value2){
            return -1;
        }else if( value1 > value2){
            return 1;
        }else{
            return 0
        }
    }
}
var data=[{name:‘Lily‘,age:29},{name:‘Lucy‘,age:39},{name:‘Jone‘,age:19},{name:‘Han‘,age:49},{name:‘Ming‘,age:9}];
data.sort(creatComparisonFuntion(‘name‘));
console.log(data);
data.sort(creatComparisonFuntion(‘age‘));
console.log(data)    

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

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

function factorial(num){
    if(num<1){
        return 1;
    }else{
        return num * factorial(num - 1)
    }
}

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

function factorial(num){
    if(num<1){
        return 1;
    }else{
        return num * arguments.callee(num - 1);
    }
}

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

var trueFactorial = factorial;
factorial = function(){
    return 0;
}
alert(trueFactorial(5)); //120
alert(factorial(5)); //0

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

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

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

function sum(num1,num2){
    return num1 + num2;
}
function callSum1(num1,num2){
    return sum.apply(this,arguments); //传入arguments对象
}
function callSum2(num1,num2){
    return sum.apply(this,[num1,num2]); //传入数组
}
console.log(callSum1(10,10)); //20
console.log(callSum2(10,10)); //20

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

function sum(num1,num2){
    return num1 + num2;
}
function callSum(num1,num2){
    return sum.call(this,num1,num2);
}
console.log(callSum(10,10));//20

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

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

window.color = ‘red‘;
var o = {color:‘blue‘};
function sayColor(){
    console.log(this.color);
}
console.log(sayColor()); //red
console.log(sayColor.call(this)); //red
console.log(sayColor.call(window)); //red
console.log(sayColor.call(o)); //blue

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

window.color = ‘red‘;
var o = {color:‘blue‘};

function sayColor(){
    console.log(this.color);
}

var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue

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

原文地址:https://www.cnblogs.com/wzndkj/p/8476888.html

时间: 2024-11-14 12:30:36

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

引用类型之Function类型

Function类型 ECMAScript中最有意思的就是函数了,有意思的根源,在于函数实际上是对象.每个函数都是Function的实例,具有属性和方法.而重要的一点是,函数名,不过是指向函数的指针,不会与某个函数绑定. 1.函数定义 (1)创建函数有函数声明法和函数表达式法.(2)函数名仅仅是指向函数的指针,所以一个函数可能会有多个名字.(3)函数没有重载,后面会覆盖前面.(4)函数声明会最先被解析,而函数表达式则不会. 1 alert(sum(10,10)); 2 function sum(

JavaScript基础——引用类型(三)Function类型

在ECMAScript中函数实际上是对象.每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定.函数通常是使用函数声明语法定义的,如: function sum(num1 , num2){ returnnum1 + num2; } 这与下面使用函数表达式定义函数的方式几乎相差无几: var sum = function(num1 , num2){ returnnum1 + num2; };

引用类型--Function类型

在ECMAScript中函数实际上是对象.每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定.函数通常是使用函数声明(定义函数的方法之一)语法定义的,如: function sum(num1 , num2){ returnnum1 + num2; } 这与下面使用函数表达式(定义函数的方法之二)定义函数的方式几乎相差无几: var sum = function(num1 , num2){

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

编程语言的基元类型 某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32();  // a = 0 a = 1; 等价于: int a = 1; 这种语法不仅增强了代码的可读性,其生成的IL代码与使用System.Int32时生成的IL代码是完全一致的. 编译器直接支持的数据类型称为基元类型(primitive type).基元类型直接映射到Framework类库(FCL)中存在的类型.如C#中,int直接映射

String类型,Function类型

1.String类型:  1)创建String对象:    var str=new String(s);    String(s);    参数:参数 s 是要存储在 String 对象中的值或转换成原始字符串的值.    返回值:当String()和运算符new一起作为构造函数使用时,它返回一个新创建的String对象,存放的是字符串s          当不用 new 运算符调用String()时,它只把 s 转换成原始的字符串,并返回转换后的值. 2)String对象属性:    leng

js——引用类型和基本类型

js中的数据类型有以下几种: Number   Boolean   undefined     Object   Function    String  Null 基本类型:Number Boolean  String  undefined null 引用类型:Object  Function 基本类型的数据是存放在栈内存中的,而引用类型的数据是存放在堆内存中的 复制变量值 基本类型: var p = 1; var p1 = p; 执行结果: 也就是说,基本类型的复制就是在栈内存中开辟出了一个新

JavaScript:Function类型

在JavaScript中,函数实际是对象.每个函数都是Function类型的实例,而且都与其他类型一样具有属性和方法.函数声明方式: // 第一种:使用函数声明语法定义 function sum (num1, num2) { return num1 + num2; } // 第二种:使用函数表达式定义函数 var sum = function(num1, num2) { return num1 + num2; }; // 第三种:构造函数 var sum = new Function("num1

浅析JavaScript之Function类型

JavaScript中的函数实际上是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上只是指向函数对象的指针,保存函数在堆内存中的地址值. 1.定义函数的三种方式: 1.1.函数声明方式 1 function sum(num1, num2){ 2 return num1 + num2; 3 } 1.2.函数表达式 1 var sum = function(num1, num2){ 2 return num1 + num2; 3

七、Function类型

七.Function类型 在ECMAScript中,Function(函数)类型实际上是对象.每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针.   1.函数的声明方式 1.普通的函数声明 function box(num1, num2) { return num1+ num2; } 2.使用变量初始化函数 var box= function(num1, num2) { return num1 + num2