zoukankan      html  css  js  c++  java
  • JS对象类型函数篇函数概述

    定义函数

    定义函数的方式有三种:函数声明语句、函数表达式和Function构造函数

    函数声明语句

    function functionName([arg1 [,arg2 [...,argn]]]) {
        statemant
    }
    

    functionName指要声明函数的名称(标识符),圆括号中是参数列表,参数之间用逗号分隔。当调用函数时,这些形参(参数列表)会被替换成实参(传入的参数)。

    【声明提升】:函数声明语句定义的函数有个特点,就是函数体和函数名称会提升。

    foo()
    function foo(){
        console.log(1)
    }
    // 1
    

    由于函数声明提升,上面的函数正常执行,相当于下面代码:

    function foo(){
        console.log(1)
    }
    foo()
    

    【重复】:如果两个函数重名了,那么后声明的函数会覆盖前声明的函数。

    function b(){
        console.log(1)
    }
    
    function b(){
        console.log(2)
    }
    b() // 2
    
    // 示例1
    var a;
    function a(){
        console.log(1)
    }
    a() // 1
    
    // 示例2
    var a = 2;
    function a(){
        console.log(1)
    }
    console.log(a) // 2
    
    // 示例3
    var a = 2;
    var a = 3;
    console.log(a) // 3
    
    // 示例4
    var a = 2;
    var a;
    console.log(a) // 2
    
    

    个人理解:如果变量只声明未初始化,则它的权重很低,重名函数或者已赋值重名变量都可以覆盖它。如果变量初始化了,那么它和重名的函数或变量权重一样,后面的会覆盖前面的。

    【删除】:函数声明语句创建的变量无法删除

    function a(){
        console.log(1)
    }
    delete a
    a() // 1
    

    函数表达式

    var funcName = function([arg1 [,arg2 [...,argn]]]){
        statement;
    }
    
    var funcName = function functionName([arg1 [,arg2 [...,argn]]]){
        statement;
    }
    

    函数表达式定义的函数,函数名字是可选的。如果没有函数名字就是匿名函数(也叫拉姆达函数)。

    var a = function(){
        console.log(1)
    }
    a() // 1
    

    当函数有名字时,函数的名字会成为一个函数内部的局部变量,这个名字相当于函数对象的形参。

    var a = function foo(){
        return foo
    }
    
    console.log(a) // foo(){ return foo }
    console.log(a()) // foo(){ return foo }
    console.log(a()()) // foo(){ return foo }
    

    Function构造函数

    var functionName = new Function(['arg1' [,'arg2' [...,'argn']]],'statement;');
    

    类似于函数表达式,但它只能创建匿名函数。不推荐使用这种方式定义函数,因为它会解析两次代码,影响性能。

    var sum = new Function('num1','num2','return num1 + num2');
    //等价于
    var sum = function(num1,num2){
        return num1+num2;
    }
    

    函数返回值

    函数中的return语句用来定义函数的返回值。

    return expression;
    

    如果函数体中没有定义return语句,或者return语句没有expression,函数返回undefined。

    var a = function(){
        return;
    }
    console.log(a()) // undefined
    

    如果函数调用时在前面加了new关键字,且返回值不是一个对象,则返回this。

    // 示例1
    function foo(){
        this.name = 'hello'
        return 1;
    }
    var test = new foo()
    console.log(test) // {name: 'hello'}
    
    // 示例2
    function foo(){
        this.name = 'hello'
        return {a: 1};
    }
    var test = new foo()
    console.log(test) // {a: 1}
    

    函数调用

    函数调用有四种方式:函数调用模式、方法调用模式、构造器调用模式和间接调用模式

    函数调用模式

    函数调用模式在非严格模式下,this指向window对象。严格模式下this是undefined。

    // 示例1
    function add(x,y){
        console.log(this);//window
    }    
    add();
    
    // 示例2
    function add(x,y){
        'use strict';
        console.log(this);//undefined
    }    
    add();
    

    可以根据this值判断当前是否是严格模式

    var isStrict = (function(){return !this;}());
    

    由于this指向全局对象,所以全局属性可能被重写

    var a = 1;
    
    function b() {
        this.a = 2
    }
    b()
    console.log(a, this.a) // 2 2 
    

    方法调用模式

    当一个函数作为对象的属性时,这个函数就是该对象的方法。方法被调用时,this绑定到该对象,所以可以通过this修改对象的属性和方法。注意是方法调用时this才绑定到该对象。

    var o = {
        a: 1,
        b: function(){
            return this
        },
        c: function(){
            this.a = 2
        }
    }
    
    console.log(o.b().a) // 1
    o.c()
    console.log(o.b().a) // 2
    

    关键字this没有作用域限制,所以嵌套的函数不会从调用他的函数中继承this。如果嵌套函数作为方法调用,则this执行调用他的函数。如果嵌套函数作为函数调用,则this指向window(非严格模式)对象或是undefined(严格模式)

    // 示例1
    var o = {
        a: function(){
            // 嵌套函数
            function b(){
              return this
            }
            return b()
        }
    }
    
    console.log(o.a()) // window
    
    // 示例2
    'use strict'
    var o = {
        a: function(){
            // 嵌套函数
            function b(){
              return this
            }
            return b()
        }
    }
    
    console.log(o.a()) // undefined
    
    

    如果想要把嵌套函数的this绑定到外部函数,可以把this保存一个临时变量。

    var o = {
        a: function(){
            var self = this
            // 嵌套函数
            function b(){
              return self
            }
            return b()
        }
    }
    console.log(o.a() === o) // true
    

    构造函数调用模式

    如果函数或者方法使用new关键字进行调用,就成为了构造函数调用。

    // 示例1
    function fn(x) {
        this.a = x
    }
    var test = new fn('good')
    console.log(test.a) // 'good'
    
    // 示例2 没有形参的构造函数可以省略圆括号
    function fn() {
        this.a = 'good'
    }
    var test = new fn
    console.log(test.a) // 'good'
    

    当使用构造函数方式调用对象的方法时,对象中的this指向新对象的上下文。

    var o = {
        name: 'good',
        a: function(){
            return this.name;
        }
    }
    var obj = new o.a();
    // this指向obj而不是o,obj没有name属性,所以结果是空对象
    console.log(obj, obj === o) // {} false
    

    构造函数通常不适用return语句,当构造函数执行完毕后,会把新对象作为调用结果返回。

    如果构造函数使用return语句但是没有指定返回值,或者返回一个原始值,那么返回值会被忽略,会把新对象作为调用结果返回。

    如果构造函数使用return语句返回一个对象,那么会把这个对象作为调用结果返回。

    // 示例1
    function fn(){
      this.a = 1
    }
    
    var test = new fn()
    console.log(test) // {a: 1}
    
    
    // 示例2
    function fn(){
      this.a = 1
      return 'hello'
    }
    
    var test = new fn()
    console.log(test) // {a: 1}
    
    // 示例3
    var obj = {name: 'hello'}
    function fn(){
      this.a = 1
      return obj
    }
    
    var test = new fn()
    console.log(test) // {name: 'hello'}
    

    间接调用模式

    JS中的函数也是对象,函数对象中的方法可以通过call()apply()间接调用,这两个方法可以显式的改变this指向,所以任何函数都可以作为任何对象的方法来调用,即使这个函数不是该对象的方法。call()方法和apply()方法有些差别:call()方法以参数列表的形式传参,apply()方法以数组的方式传入参数。

    var obj = {}
    function sum(x,y){
       return x + y
    }
    
    console.log(sum.call(obj, 1,2)) // 3
    console.log(sum.apply(obj, [1,2])) // 3
    
    优秀文章首发于聚享小站,欢迎关注!
  • 相关阅读:
    设计模式-总览
    restful
    springmvc异常统一处理(二)
    springmvc参数校验(二)
    跨语言的RPC
    更安全的RPC接口
    RPC版 “Hello World”
    用例(Use Case)
    参与者
    数据库知识基础入门
  • 原文地址:https://www.cnblogs.com/yesyes/p/15351889.html
Copyright © 2011-2022 走看看