函数调用的四种模式

时间:2021-2-20 作者:admin

调用一个函数会暂停当前函数的执行,传递控制权和参数给新函数。除了声明时定义的形式参数(parameters),每个函数还接收两个附加参数:thisarguments(实际参数)。参数this的值在面向对象中取决于调用的模式。
当实际参数大于形式参数时并不会产生错误,多余的实际参数会被忽略,
当实际参数小于形式参数时缺失的部分会抛出undefined
在JS中函数的调用有四种模式:

  1. 方法调用模式
  2. 函数调用模式
  3. 构造函数调用模式
  4. apply调用模式

一、方法调用模式

当一个函数被保存做对象的一个属性时,我们称作方法.当方法被调用时,this会被绑定到该对象.如果调用表达式包含一个提取属性的动作(即”.“或”[]“),那么它就是被当做一个方法调.

 // 创建obj对象,它有一个value属性和increment方法
        let obj = {
            value: 0,
            increment: function (inc) {
                this.value += typeof inc === 'number' ? inc : 1
                // 调用increment方式时传入的参数是数字,则参数+=value,否则+=1
            }
        }
        obj.increment();//初始0
        console.log(obj.value);//0+=1
        obj.increment(2);//如果是数字经过上面两层操作后1+=2
        console.log(obj.value);//3

方法可以使用this访问自己所属的对象,所以它能从对象中取值或对对象进行修改.this到对象的绑定发生在调用的时候.这个”超级”延迟绑定使得函数可以对this高度复用.通过this可取得它们所属对象的上下文的方法称为公共方法(public method)

二、函数调用模式

当一个函数并非对象的属性时,那么它就是被当作一个函数来调用的:

 let sum = function (a, b) {
                    console.log(this);
                    return a + b
                }
                console.log(sum(3, 4));

以此方式调用函数时,this会被绑定到全局对象.这个是语言设计上的错误,倘若语言设计正确,name当内部函数被调用时,this应该仍然绑定到外部函数的this变量.这个设计错误的后果是方法不能利用内部函数来帮助它工作,因为内部函数的this被绑定了错误的值,所以不能共享该方法对对象的访问权.
解决方法:给该对象定义一个变量并赋值为this,那么内部对象就可以通过这个变量访问到this,这里示范为that.

 // 创建obj对象,它有一个value属性和increment方法
        let obj = {
            value: 0,
            increment: function () {
                // 调用increment方式时传入的参数是数字,则参数+=value,否则+=1
                this.value += typeof inc === 'number' ? inc : 1
                let that = this
                // 内置对象
                let sum = function (a, b) {
                    that.value = a + b
                    return
                }
                sum(3, 4);
            },
        }
        obj.increment();//初始0
        console.log(obj.value);//7,如果不加变量转换this指向则为1

三、构造器调用模式

如果在一个函数面前加上new来调用,那么背地里会创建一个连接到该函数的prototype成员的新对象,同时this会被绑定到那么新对象上.

        //创建一个名为Quo的构造器函数,它构造一个带有status属性的对象.
        let Quo = function (string) {
            this.status = string
        }
        console.log(Quo.prototype);
        //给Quo的所有实例提供一个名为get_status的公共方法
        Quo.prototype.get_status = function () {
            return this.status
        }
        console.log(Quo.prototype);//出现get_status方法
        //构造一个Quo实例
        let myQuo = new Quo('confused')
        console.log(myQuo.status);//confused
        console.log(myQuo.get_status());//confused
        console.log(myQuo);
        console.log(typeof myQuo.get_status);//function

一个函数,如果创建的目的希望是结合new前缀来调用,那么就被称作构造器函数,按照约定,它们会被保存在以大写格式命名的变量里.如果调用构造器函数时没有在前面加上new,那么即没有编译时警告,也没有运行时警告,所以大写约定非常重要.
但不推荐使用这种形式的构造器函数.

四、Apply调用

Apply方法让我们构造一个参数数组传递给调用函数,它允许我们选择this的值.
Apply方法接收两个参数,第一个是要绑定给this的值,第二个是参数数组

        let person = {
            firstName: "Bill",
            lastName: "Gates",
        }
        let person1 = ["+", 4]
        let person2 = {
            fullName: function (item, item2) {
                return this.firstName + item + item2
            }
        }
        let x = person2.fullName.apply(person, person1)
        console.log(x);//Bill+4

试试挂到prototype

       //构造一个包含status成员的对象
        let staObj = {
            status: '山竹'
        }
        //staObj并没有继承来自Quo.prototype,但可以在staQuo上调
        // 用get_status方法,尽管staObj没有一个名为get_sta的方法
        let sta = Quo.prototype.get_status.apply(staObj)
        console.log(sta);//山竹

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。