zoukankan      html  css  js  c++  java
  • js之数据类型(对象类型——构造器对象——函数1)

      函数它只定义一次,但可以被多次的执行和调用。JavaScript函数是参数化的,函数的定义会包括形参和实参。形参相当于函数中定义的变量,实参是在运行函数调用时传入的参数。

      一、函数定义

        函数使用function关键字来定义。它可以用在函数定义表达式或者函数声明语句里。    

        1、函数声明语句

        使用function关键字,后跟一组参数及函数体。

        funcname是要声明的函数名称标识符。函数名称是函数声明语句必需的部分。

        圆括号其中可以包含由0个或者是多个用逗号隔开的标识符组成的列表,这些标识符是函数的参数名称,它们就像是函数体中的局部变量一样。

        花括号,包偏一条或者是多条javascript语句。这些语句构成函数体,一旦调用函数,就会执行这些语句。

        变量的重复声明是无用的,但是函数的重复声明会覆盖前面的声明(无论是变量还是函数声明)

        <!-- <script>
            语法:
            function funcname() {
                statement;
            } 
            调用:
            1、funcname(参数);
            2、把函数声明变成函数表达式在后面加上一对小括号
        </script> -->

        2、函数表达式

         以表达式的方式来定义函数,函数的名称是可选的。

         匿名函数是function关键字后面没有标识符的函数。通常而言,以表达式方式定义函数时都是不需要名称的,这样做的好处是让代码更加简洁。函数定义表达式特别适合用来定义那些只会使用一次的函数。

       <!-- <script>
            语法:
            let functionName = function (参数) {
                statement;
            }
         let functionName = function funcName(){
           statement;
         } 调用: 1、变量(参数); 2、直接在后面加上小括号 注意:函数表达式里的function后面如果有名字的话,在调用的时候不能用这个名字去调用 </script>
    -->

        3、Function构造函数

        Function构造函数接收任意数据的参数,但最后一个参数始终都被看成是函数体,前面的参数则枚举出了新函数的参数。Function构造函数无法指定函数名称,它创建了一个匿名函数。不推荐使用。会导致两次代码的解析。

        <!-- <script>
            语法:
            var functionName=new function(){
                statement;
            }
        </script> -->

       二、函数参数 

         从函数外向函数内传入数据,在函数内可以接受到这些数据且能够使用它,这些数据就叫做参数。由于js是弱语言类型,所以js函数的参数与大多数其它语言参数有所不同,函数不介意传递进来的参数是什么类型,甚至是可以不传参。

         参数放在小括号内,可以放0个或者是多个,用逗号隔开。

         参数分为形参和实参。形参是形式上的参数,在函数声明的小括号里,形参实际上是由实参来决定的。在非严格模式下,函数中可以出现同名的形参且只能访问最后出现的该名称的形参。但在严格模式下会报错。

         实参是实际上的参数,放在了函数调用的小括号里,实参须与形参一一对应,在调用函数的时候,要把实参传够数量,如果有一个实参没有传,那它就是undefined。常常用逻辑或运算符给省略的参数设置一个合理的默认值

          js中的参数在内部用一个数组表示。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数。在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数.

          arguments对象:代表了所有实参的集合,它是一个类数组。这个集合中的每个数据都有一个自己对应的下标,集合中还有一个length,代表了实参的个数(函数的length属性显示形参的个数)它只能在函数内使用,在函数外是用不了的,如果函数外使用,会报错。arguments对象中的值永远与对应命名参数的值保持同步,arguments对象与命名参数并不是访问相同的内存空间,它们的内存空间独立,但是值相等。

         ECMAScript中所有函数的参数都是按值传递的。换句话说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。

        <script>
            function person(name, age) {
                //形参实际上就是在函数里声明的变量,变量的初始值是undefined.在函数调用时,把实参传入进来,变成真实的值
                console.log(name, age); //davina 20
            }
            person('davina', 20);
    
            function add(x, x) {
                return x;
            }
            console.log(add(1, 2)); //2
    
            /* function add(x,x){
                 'use strict'
                 return x;
             }
             cosole.log(add(1,2));  //报错 */
    
            function fn(x, y) {
                console.log(x, y);  //1 undefined
            }
            fn(1);
    
            function add(x, y) {
    
                console.log(arguments[0], arguments[1], arguments[2], arguments.length);  //1 2 3 3
                return x + 1;
            }
            add(1, 2, 3);
            console.log(add.length);//2
        </script>
        <script>
            //传递一个基本类型值时,被传递的值会被赋给一个局部变量
            function add(num) {
                num += 10;
                return num;
            }
            let count = 10;
            let re = add(count);
            console.log(re, count);//20 10
            //变量作为参数传递给函数,在函数内部,参数num被加10,这一变化不会影响函数外面的值。
    
            //向参数传递引用类型值时
            function fn(obj) {
                obj.name = 'davina';
            }
            let person = new Object();
            fn(person);
            console.log(person.name); //davina
        //函数外部创建一个对象person,然后用fn来进行调用,person的值复制一份后传递给参数obj,使得obj的引用与person指向同一对象
        </script>

      三、函数调用

        只有函数被调用时才会执行,调用运算符是跟在任何一个函数值的表达式后的一对圆括号。圆括号内可以包括多个用逗号隔开的表达式,每个表达式产生一个参数值,每个参数值被赋予函数声明时定义的形参名。js的函数调用会出现两个额外的参数,arguments和this.argument是参数组,它并不是一个真实的数组但还是可以通过.lenght方法获得长度。函数调用分为以下4种:

        1、函数调用模式(函数名(参数 ))

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

        <script>
            let add = function (a, b) {
                // 'use strict';
                // console.log(this); //undefined
    
                alert(this);//Window
                
                return a + b;
            }
            let sum = add(3, 4);//7;
            console.log(sum);
        </script>

        使用函数调用模式调用函数时,在非严格模式下,this指向window,在严格模式下this指向undefined。

        2、方法调用模式  ( 对象.方法(参数) )

        当一个函数被保存为对象的一个属性时,我们称它为一个方法,当一个方法被调用时,this被绑定到该对象。如果调用表达式包含一个提取属性的动作,那么它就是被当做一个方法来调用。(简而言之方法调用就是用对象的方法调用,所以说方法对象一定要有宿主对象)。

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

        任何函数只要作为方法调用都会传入一个隐匿的实参,这个实参是一个对象,方法调用的母体就是这个对象。

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

        所以总结来看:方法调用模式不是独立的,需要宿主,而函数调用模式是独立的

               方法调用模式方法:obj.fn(),函数调用模式方法:fn();

               方法调用模式中,this指宿主,而函数调用模式中this指全局对象

        <script>
            let myObject = {
                value: 0,
                fn1: function () {
                    console.log(this);//myObject
                    return this;
                },
                fn2: function () {
                    console.log(this);//myObject
                    this.value = 1;
                },
                fn3:function(){
                    function n(){
                        console.log(this);//window
                        return this;
                    }
                    return n();
                }
            }
    
            console.log(myObject.fn1().value);//0
    
            myObject.fn2();
            console.log(myObject.fn1().value);//1
    
            console.log(myObject.fn3());//window
        </script>

        3、构造器调用模式

          如果函数或者方法调用之前带有关键字new.那么它就构成构造函数调用。new是一个运算符,专门用来申请创建对象,创建出来的对象传递给构造函数的this,然后利用构造函数对其初始化。

          执行步骤:var p = new Person();

          如果构造函数调用在圆括号内包含一组实参列表,先计算这些实参表达式,然后传入函数内。如果构造函数没有形参,js构造函数调用的语法是允许省略实参列表和圆括号的。凡是没有形参的构造函数调用都可以省略圆括号。

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

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

        4、间接调用模式

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

         这两个方法都允许显式指定调用所需的this的值,可以修改this的指向。call()方法使用它自有的实参列表作为函数的实参,apply()方法则要求以数组的形式传入参数。

         语法:call形式:函数名.call()   apply形式:函数名.apply()    bind形式:函数名.bind()

           call()和apply()的相同点:两个方法都使用了对象本身作为第一个参数,都是用来改变this的指向。

         call()和apply()的不同点:apply()第二个参数是数组;call()第二参数是参数列表。 在js的严格模式下,在调用函数时第一个参数会成为this的值,即使该参数不是一个对象,在非严格模式下,如果第一个参数的仠是null或者是undefined,它将使用全局对象替代。

         bind() :call()改过this指向后,会再执行函数,bind()改过this后,不执行函数,会返回一个绑定新this的函数。

        <script>
            let obj = {};//定义一个空对象
            function fn(x, y) {
                console.log(this);//obj
                console.log(x, y);//1,2
            }
            fn.apply(obj, [1, 2]);
            fn.call(obj, 1, 2);//直接调用
            let b = fn.bind(obj);//bind()不能调用函数
            b();//此时才调用
        </script> 

        四、函数返回值

        函数中的return语句用来返回函数调用后的返回值,阻止函数继续运行。它经常作为函数的最后一条出现,当return被执行时,函数立即返回不再执行余下的语句。如果函数里没有return,那这个函数的返回值结果就是undefined。它只能出现在函数体内,如是不是那就会报错。一个函数中可以有多个return语句。

    <script>
        function fn(a, b) {
            return a + b;
            alert(1); //不会执行,因为放在了return后面
        }
        console.log(fn(2, 3));  //5
    
        function fn1(a, b) {
            let c = a + b;
        }
        console.log(fn1(4, 5));//undefined 函数里没有return
    </script>

      return例子:点击按钮,在按钮后方放入相加的值

        <script>
            window.onload = function () {
                let btns = document.querySelectorAll("input[type=button]");
                let texts = document.querySelectorAll("input[type=text]");
                function add() {
                    let result=0;
                    for (var i = 0; i < arguments.length; i++) {
                        result += arguments[i];
                    }
                    return result;
                }
                btns[0].onclick=function(){
                    texts[0].value=add(12,34,56,78);
    
                };
                btns[1].onclick=function(){
                    texts[1].value=add(12,56,78);
    
                }
            }
        </script>
        <input type="button" value="按钮一">
        <input type="text">
        <input type="button" value="按钮二">
        <input type="text">

     

     

      

  • 相关阅读:
    398. Random Pick Index
    382. Linked List Random Node
    645. Set Mismatch
    174. Dungeon Game
    264. Ugly Number II
    115. Distinct Subsequences
    372. Super Pow
    LeetCode 242 有效的字母异位词
    LeetCode 78 子集
    LeetCode 404 左叶子之和
  • 原文地址:https://www.cnblogs.com/davina123/p/11858857.html
Copyright © 2011-2022 走看看