• Js基础知识4-函数的三种创建、四种调用(及关于new function()的解释)


    在js中,函数本身属于对象的一种,因此可以定义、赋值,作为对象的属性或者成为其他函数的参数。函数名只是函数这个对象类的引用。

    函数定义

     1 // 函数的三种创建方法(定义方式)
     2 function one(){                                 // 函数声明语句,不属于任何对象,始终默认为全局对象
     3 console.log("第一个函数")
     4 //默认有一个return this,返回函数中的内容
     5 }
     6 one();      //必须调用;可以在函数声明前调用(预处理变异机制)                       
     7 
     8 var fn=function(){                               //函数定义表达式
     9 console.log("第二个函数")
    10 }
    11 fn(); //必须先声明再调用                                 
    12 
    13 var fun=new Function(console.log("第三个函数"));    //Function构造函数 无需调用,会自调  
    //实际一般应这样写:var newFun = new Function("x","return alert(x)");
    //[注意]Function构造函数无法指定函数名称,它创建的是一个匿名函数。

    从技术上讲,这是一个函数表达式。但不推荐使用,因为这种语法会导致解析两次代码。第一次是解析常规javascript代码,第二次解析传入构造函数中的字符串,影响性能。

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

    [注意]并不是所有的函数都可以成为构造函数 

    1 var o = new Math.min();//Uncaught TypeError: Math.min is not a constructor

    【重复声明】变量的重复声明是无用的,不会覆盖之前同一作用域声明的变量,但函数的重复声明会覆盖前面的声明的同名函数或同名变量

    //变量的重复声明无用
    var a = 1;
    var a;
    console.log(a);//1
    
    1 //覆盖同名变量
    2 var a;
    3 function a(){
    4     console.log(1);
    5 }
    6 a();//1
    1 //覆盖同名函数
    2 a();//2
    3 function a(){
    4     console.log(1);
    5 }
    6 function a(){
    7     console.log(2);
    8 }

    【删除】函数声明语句创建的变量无法删除,这一点和变量声明一样。

    1 function foo(){
    2     console.log(1);
    3 }
    4 delete foo;//false
    5 console.log(foo());//1

    ———————————————————

    函数调用

    javascript一共有4种调用模式:函数调用模式、方法调用模式、构造器调用模式和间接调用模式

    【1】函数调用模式

      当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用的。对于普通的函数调用来说,函数的返回值就是调用表达式的值。

    1 function add(x,y){
    2     return x+y;
    3 }
    4 var sum = add(3,4);
    5 console.log(sum)//7

    使用函数调用模式调用函数时,非严格模式下,this被绑定到全局对象;在严格模式下,this是undefined

    function add(x,y){
        console.log(this);//window
    }    
    add();//window
    function add(x,y){
        'use strict';    //严格模式
        console.log(this);//undefined
    }    
    add();//undefined

    因此,’this’可以用来判断当前是否是严格模式

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

    【重写】因为函数调用模式的函数中的this绑定到全局对象,所以会发生全局属性被重写的现象

    1 var a = 0;
    2 function fn(){
    3     this.a = 1;
    4 }
    5 fn();
    6 console.log(this,this.a,a);//window 1 1

    【2】方法调用模式

    当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象。如果调用表达式包含一个提取属性的动作,那么它就是被当做一个方法来调用。

    var o = {
        m: function(){
            console.log(1);
        }
    };
    o.m();//1

    方法可以使用this访问自己所属的对象,所以它能从对象中取值或对对象进行修改。this到对象的绑定发生在调用的时候。通过this可取得它们所属对象的上下文的方法称为公共方法。

    var o = {
        a: 1,
        m: function(){
            return this;
        },
        n: function(){
            this.a = 2;
        }
    };
    console.log(o.m().a);//1
    o.n();
    console.log(o.m().a);//2

    和变量不同,关键字this没有作用域的限制,嵌套的函数不会从调用它的函数中继承this。如果嵌套函数作为方法调用,其this的值指向调用它的对象。如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式下)就是undefined(严格模式下)

    var o = {
        m: function(){
             function n(){
                 return this;
             }
             return n();
        }
    }
    console.log(o.m());//window
    var o = {
        m: function(){
             function n(){
                 'use strict';
                 return this;
             }
             return n();
        }
    }
    console.log(o.m());//undefined

    如果想访问这个外部函数的this值,需要将this的值保存在一个变量里,这个变量和内部函数都同在一个作用域内。通常使用变量_this、that或self来保存this

    var o = {
        m: function(){
            var self = this;
            console.log(this === o);//true
             function n(){
                 console.log(this === o);//false
                 console.log(self === o);//true
                 return self;
             }
             return n();
        }
    }
    console.log(o.m() === o);//true

    【3】构造函数调用模式

      如果函数或者方法调用之前带有关键字new,它就构成构造函数调用

    function fn(){
        this.a = 1;
    };
    var obj = new fn();
    console.log(obj.a);//1

    如果构造函数调用在圆括号内包含一组实参列表,先计算这些实参表达式,然后传入函数内

    function fn(x){
        this.a = x;
    };
    var obj = new fn(2);
    console.log(obj.a);//2

    如果构造函数没有形参,javascript构造函数调用的语法是允许省略实参列表和圆括号的。凡是没有形参的构造函数调用都可以省略圆括号

    var o = new Object();
    //等价于
    var o = new Object;

    [注意]尽管构造函数看起来像一个方法调用,它依然会使用这个新对象作为调用上下文。也就是说,在表达式new o.m()中,调用上下文并不是o

    var o = {
        m: function(){
            return this;
        }
    }
    var obj = new o.m();
    console.log(obj,obj === o);//{} false
    console.log(obj.constructor === o.m);//true

    构造函数通常不使用return关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值

    function fn(){
        this.a = 2;
    }
    var test = new fn();
    console.log(test);//{a:2}

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

    function fn(){
        this.a = 2;
        return;
    }
    var test = new fn();
    console.log(test);//{a:2}

    如果构造函数显式地使用return语句返回一个对象,那么调用表达式的值就是这个对象

    var obj = {a:1};
    function fn(){
        this.a = 2;
        return obj;
    }
    var test = new fn();
    console.log(test);//{a:1}

    【4】间接调用模式

      javascript中函数也是对象,函数对象也可以包含方法。call()和apply()方法可以用来间接地调用函数。

      这两个方法都允许显式指定调用所需的this值,也就是说,任何函数可以作为任何对象的方法来调用,哪怕这个函数不是那个对象的方法。两个方法都可以指定调用的实参。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

    (函数返回值、函数参数、函数属性、函数方法)另开篇章

    js的运行机制问题:(声明提升) 
    1、在js中js引擎会优先解析var变量和function定义!在预解析完成后从上到下逐步进行! 
    2、解析var变量时,会把值存储在“执行环境”中,而不会去赋值,值是存储作用!例如: 
    alert(a); var a = 2; 这时会输出undifiend,意思是没有被初始化没有被赋值! 
    这并不是没有被定义,错误了的意思! 
    3、在解析function时会把函数整体定义,这也就解释了为什么在function定义函数时为什么可以先调用后声明了!其实表面上看是先调用了,其实在内部机制中第一步实行的是把以function方式定义的函数先声明了(预处理)

    //*****************上篇出自:https://blog.csdn.net/luanpeng825485697/article/details/77010261

    //*****************下篇出自:https://www.cnblogs.com/hss-blog/articles/9358251.html

    //js中只有new Function没有new function,或者我理解你说的new function是指实例化一个对象
    //new Function的作用是从字符串中创建一个匿名方法,如下:
    var newFun = new Function("alert(1)");
    nweFun();        //弹出1
     
    //如果你说的new function是实例化一个对象,那么代码如下:
    function cls(){
        this.helloWord = function(){
            alert("hello Word!");
        }
    }
    var clsObj = new cls();
    clsObj.helloWord();        //弹出hello Word!
    //这里的cls这个你应该要把他看成面向对象里面的类,而不是js里面的方法。
    //当然本质上他就是一个方法,而且你也可以cls()这样直接调用。
    //更多js面向对象的东西我就不细说了,你可以自行百度。
     
    //直接定义个function,然后调用,代码如下:
    function fun(){
        alert("hello Word!");
    }
    fun();            //弹出hello Word!
    //这里的方法你应该看成面向对象里面的静态方法,而不是面向对象里面的类。
    //当然他也确实是一个类,你也可以new fun()来调用。
    //但是new fun()得到的对象没有任何方法。

    //其实关于new function 应该是这样的( 更准确的说应该是new function()
    var clsObj = new function()
    {
    this.helloWord = function(){
    alert("hello Word!");
    }
    }
    clsObj.helloWord(); //弹出hello Word!
    //是实例化一个对象(匿名函数),这样写的好处是可以防止没有new调用函数

    看到一个new Function用法

    function callAnotherFunc(fnFunction, vArgument) {
      fnFunction(vArgument);
    }
    var doAdd = new Function("iNum", "alert(iNum + 10)");
    callAnotherFunc(doAdd, 10);    //输出 "20"
  • 相关阅读:
    final,static,this,super 关键字总结
    Java基础知识(三)
    Java基础知识(二)
    Java基础知识(一)
    MyBatis重要核心概念
    Mybatis执行SQL的完整过程及四大组件介绍
    Mybatis之plugin插件设计原理
    Spring MVC 9大组件概述
    Log4j的使用
    Git的介绍及使用
  • 原文地址:https://www.cnblogs.com/7qin/p/9606489.html
Copyright © 2020-2023  润新知