JS函数的4种调用模式

若有不妥,请多指教
<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply">学习网址推荐</a>

JS函数的4种调用模式包括:
1.函数模式
2.方法模式
3.构造函数模式
4.上下文模式(也有叫apply模式)


1.函数模式

就是最基本的函数

        function test1() {
            //this指向window全局对象
            console.log(this);
        }
        test1();

2.方法模式

我们创建一个对象,这个对象有一个函数,那这个函数就叫方法,通过对象调用方法的模式

        var obj2 = {
            test2:function () {
                //this指向调用这个方法的对象
                console.log(this);
            }
        }
        obj2.test2();

3.构造函数模式

构造函数的注意事项:
1>首字母要大写
2>构造函数中的this指定的是创建出来的对象
3>函数默认返回的是创建出来的对象

3.1构造模式:

        function Star(name,age) {
            this.name = name;
            this.age = age;
            this.sayHello = function () {
               //this指向使用new创建出来的对象
                console.log(this.name + 'hi');
            }
        }
        var star = new Star("邱淑贞",18);
        star.sayHello();

3.2工厂模式:
工厂就是用来模式化生产东西的, 因此如果函数创建对象并返回, 就称该函数为工厂函数

        function Star(name,age) {
            var obj = {
                name:name,
                age:age,
                sayHello:function () {
                    console.log(this.name + 'hi');
                }
            }
            return obj;
        }
        var star = Star("邱淑贞",18);
        star.sayHello();

或者这种写法

        function Star(name,age) {
            var obj = new Object();
            obj.name = name;
            obj.age = age;
            obj.sayHello = function () {
                console.log(this.name + 'hi');
            }
            return obj;
        }
        var star = Star("邱淑贞",18);
        star.sayHello();

3.3寄生式构造函数模式:
提到工厂模式就不得不提寄生式构造函数
可以看出二者的不同就是调用时一个用new,一个没有用new

        function Star(name,age) {
            var obj = {
            }
            obj.name = name;
            obj.age = age;
            obj.sayHello = function () {
                console.log(this.name + 'hi');
            }
            return obj;
        }
        var star = new Star("邱淑贞",18);
        star.sayHello();

作用嘛寄生构造函数专门用来为js原生的构造函数扩展新的方法
假设我们想创建一个具有额外方法的特殊数组
由于不能直接修改Array构造函数,所以我们可以使用寄生模式

function SpecialArray() {
    //创建数组
    var array=new Array();
    //添加值  arguments获取的是实参,不是形参,所以SpecialArray()并没有形参接收传递过来的参数
    array.push.apply(array,arguments);
    array.toPipedString=function(){
        return this.join("|");
    }
    return array;
}
var colors=new SpecialArray("red","blue","black");
alert(colors.toPipedString());  //输出:red|blue|black

4.上下文模式

可以看出,前面三种函数调用模式的最主要区别就是this的指向不同
而上下文模式最主要的功能就是可以修改this的指向,指定的谁就是谁

实现方式为:
1>函数.call(对象,参数1,参数2,参数3,参数4)
2>函数.apply(对象,数组)
二者都可以用来改变this的指向为参数的第一个值(对象)

第一个参数:
如果传入的是一个对象, 那么就相当于设置该函数中的 this 为参数
如果不传入参数, 或传入 null undefiend 等, 那么相当于 this 默认为 window

第二个参数:
在使用此模式调用的时候, 原函数(方法)可能会带有参数, 那么这个参数使用第二个( 第 n 个 )参数来表示
call在函数的形参个数确定的情况下使用
apply在函数的形参个数不确定的情况下使用

如果是函数调用test(), 那么有点类似于test.apply(window)
如果是方法调用obj.method(), 那么有点类似于obj.method.apply(obj)

MDN搜索function.prototype.apply().png

看一个简单的例子:
运行结果是打印两次"邱淑贞漂亮等级为:100级"
而不是王祖贤

        var name = "王祖贤";
        function sayHello(a,b) {
            console.log(this.name + '漂亮等级为:' + (a * b) + '级');
        }

        var obj = {
            name:"邱淑贞"
        }
        
        sayHello.apply(obj,[10,10]);
        sayHello.call(obj,10,10);

再看一个快速打印数组中最大值的例子:
运行结果是打印66

        var arr = [9,12,23,22,11,33,66];
        var max = Math.max.apply(null,arr);
        console.log(max);

再看一个将所有参数用-连接起来的例子:
运行结果为打印
0: "66-王祖贤-邱淑贞-覃芳菲-都是大美女-66"
1: "66+王祖贤+邱淑贞+覃芳菲+都是大美女+66"

        function test() {
            //arguments是所有形参的集合
            //在函数中,使用特殊对象arguments,无需明确指出参数名,就能访问它们
            var str1 = Array.prototype.join.apply(arguments,["-"]);
            var str2 = Array.prototype.join.call(arguments,"+");
            var arr = [str1,str2];
            return arr;
        }
        var arr = test(66,"王祖贤","邱淑贞","覃芳菲","都是大美女",66);
        console.log(arr);

值得注意的是:
当用call和apply传入的第一个参数为值类型的时候,会将值类型转换成对应的对象(引用类型)然后赋值给this
当传入的第一个参数为 null或者undefined的时候,会把this赋值为window

        function test() {
            console.log(this);
        }

        test.apply(1);          //打印Number
        test.apply("abc");      //打印String
        test.apply(true);       //打印Boolean
        test.apply(undefined);  //打印Window
        test.apply(null);       //打印Window

4.1借用构造函数实现继承:
运行结果为打印Star {name: "邱淑贞", age: 18}

        function Person(){
            this.name = "邱淑贞";
            this.age = 18;
        }

        function Star(){
            var star = this;
            Person.apply(star);
        }

        var star = new Star();
        console.log(star);

推荐阅读更多精彩内容

  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,322评论 2 17
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 2,817评论 0 4
  • 在js中,函数本身属于对象的一种,因此可以定义、赋值,作为对象的属性或者成为其他函数的参数。函数名只是函数这个对象...
    Mockingbird_7阅读 445评论 0 5
  • 函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 上面代码检查函数l...
    呼呼哥阅读 2,602评论 0 1
  • 我闲着无聊刚好想找工作然后就把手机上的短信翻来看然后看到加qq面试有工作,我就把几个qq加了。 然后不一会儿就加上...
    我只是个迷妹纸阅读 278评论 0 0
  • 前几天买了个kindle,结果就一发不可收拾的使劲往里屯书,在不同的地方自然而然的会对kindle这几个字眼格外关...
    代号551丿50阅读 326评论 0 1
  • 1研究生时,刚进实验室,坐在靠门的最里边。斜对面,对角线位置,坐着一位师兄。高我两届,当时他研三,马上要毕业了。我...
    littlersmall阅读 790评论 1 51
  • Someone told me long ago There is a calm Before the storm...
    Gina66阅读 467评论 0 0