zoukankan      html  css  js  c++  java
  • 《JavaScript设计模式与开发》笔记 3.call和apply

    •  1.改变this指向
    •  2.Function.prototype.bind
    •  3.借用其他对象方法
      • 1.借用实现继承
      • 2.实现恶心的
        • Array.prototype.push.call
        • Array.prototype.join.call
        • Array.prototype.slice.call
        • Object.prototype.toString.call

    1.改变this指向

    var obj1 = {
        name:"Bob marley"
    };
    var obj2 = {
        name:"Bob Dylan"
    };
    var name = "David Bowie";
    var getName = function(){
        console.log(this.name);
    }
    getName();  //输出undefined
    getName.call(obj1); //输出Bob marley
    getName.call(obj2); //输出Bob Dylan

    在实际开发中,经常会遇到this指向被不经意改变的场景:例如:

    document.getElementById('div1').onclick=function(){
        alert(this.id);         //输出div1
        var func = function(){
            alert(this.id);     //输出undefined
        }
        func();
    };

    使用call来修复func函数内的this,使其指向div

    document.getElementById('div1').onclick=function(){
        alert(this.id);
        var func = function(){
            alert(this.id);
        }
        func.call(this);
    };
    再如:
    
    var name = "SmarTom";
    var func = function(){
        console.log(this.name);
    }
    func();

    使用call来修复func函数内的this,使其指向div 再如:

    var obj ={
        name : "SmarTom"
    }
    var func = function(){
        console.log(this.name);
    }
    func.call(obj);

    2.Function.prototype.bind

    大部分浏览器都实现了内置的Function.prototype.bind,用来指定函数内部的this指向 即使没有原生的Function.prototype.bind实现,也可以模拟一下,例如:

    //在一些浏览器中可以忽略 bind函数
    Function.prototype.bind = function(context){
        var _self = this;
        return function(){
            return _self.apply(context,arguments);
        }
    }
    var obj = {
        name :"SmarTom"
    }
    var func = function(){
        console.log(this.name);
    }.bind(obj);            //进行绑定
    func();
     

    3.借用其他对象的方法【实现继承】

    1.借用实现继承

    var A = function(name){                 //父类 A
        this.name = name;
    }
    var B = function(){                     //子类 B 继承父类A
        A.apply(this,arguments);
    }
    B.prototype.getName = function(){       //B方法
        return this.name;
    }
    var b = new B('asdfasdfasdf');
    console.log(b.getName());

    2.实现

    Array.prototype.push.call
    Array.prototype.join.call
    Array.prototype.slice.call
    Object.prototype.toString.call()
    
    
    1. Array.prototype.push.call
    Array.prototype.push.call(obj,arguments)
    相当于var html = []; html.push(那一大堆)
    <script type="text/javascript">
        (function () {
            var customService = function () {
    
            };
            customService.prototype = {
                open: function () {
                   contents: this._getHtml(),
                },
                close: function () {
    
                },
                _getHtml: function () {
                    var html = [];
                    Array.prototype.push.call(html,
                        '<div class="content">',
                            '<div>1、</div>',
                            '<div>2、</div>',
                            '<div>3、</div>',
                            '<div>4、</div>',
                        '</div>'
                    );
                    return html.join('');
                }
            };
            window.CustomService = new customService();
        })();
    </script>
    
    2.Array.prototype.join.call
    //arguments就相当于一个对象数组
    Array.prototype.join.call(arguments,',')
    就类似于window.join方法.apply,call不会改变scope,可参考finally里的内容
    <script type="text/javascript">
    var join = function () {
        for (var i = 0, b = ''; i < this.length ; i ++) {
            if (i) b+= arguments[0];
            b += this[i];
        }
        return b;
    };
     
    var show = function () {
        //new Array(arguments)).join('_');
        //try
        try {
            alert(
                Array.apply(null, arguments).join('_')
            );
            return join.call(arguments, '-'); //Array.prototype.join就类似于window.join方法.apply,call不会改变scope,可参考finally里的内容
        } finally {
            var func = function () {
                alert(a);
            };
     
            void function () {
                var a = 1;
                try {
                    func.call(this);
                } catch (exp) {
                    alert(exp.message);
                }
            }();
        }
    };
     
    alert(show(1, 2, 3, 5));
    </script>
    
    
    3.Array.prototype.slice.call
    var a={length:2,0:'first',1:'second'};
    Array.prototype.slice.call(a);//  ["first", "second"]
    var a={length:2};
    Array.prototype.slice.call(a);//  [undefined, undefined]
    可能刚开始学习js的童鞋并不是很能理解这句为什么能实现这样的功能。
    比如我就是一个,所以,来探究一下。
    首先,slice有两个用法,一个是String.slice,一个是Array.slice,
    第一个返回的是字符串,第二个返回的是数组,这里我们看第2个。
    Array.prototype.slice.call(arguments)能够将arguments转成数组,那么就是arguments.toArray().slice();
    到这里,是不是就可以说Array.prototype.slice.call(arguments)的过程就是先将传入进来的第一个参数转为数组,再调用slice?
    
    
    4.Object.prototype.toString.call
    使用Object.prototype上的原生toString()方法判断数据类型,使用方法如下:
    
    Object.prototype.toString.call(value)
    
    1.判断基本类型:
    
    Object.prototype.toString.call(null);//”[object Null]”
    Object.prototype.toString.call(undefined);//”[object Undefined]”
    Object.prototype.toString.call(“abc”);//”[object String]”
    Object.prototype.toString.call(123);//”[object Number]”
    Object.prototype.toString.call(true);//”[object Boolean]”
    2.判断原生引用类型:
    
    函数类型
    Function fn(){console.log(“test”);}
    Object.prototype.toString.call(fn);//”[object Function]”
    日期类型
    var date = new Date();
    Object.prototype.toString.call(date);//”[object Date]”
    数组类型
    var arr = [1,2,3];
    Object.prototype.toString.call(arr);//”[object Array]”
    正则表达式
    var reg = /[hbc]at/gi;
    Object.prototype.toString.call(arr);//”[object Array]”
    自定义类型
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    var person = new Person("Rose", 18);
    Object.prototype.toString.call(arr); //”[object Object]”
    很明显这种方法不能准确判断person是Person类的实例,而只能用instanceof 操作符来进行判断,如下所示:
    console.log(person instanceof Person);//输出结果为true
    3.判断原生JSON对象:
    
    var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);
    console.log(isNativeJSON);//输出结果为”[object JSON]”说明JSON是原生的,否则不是;
    
    注意:Object.prototype.toString()本身是允许被修改的,而我们目前所讨论的关于
    Object.prototype.toString()这个方法的应用都是假设toString()方法未被修改为前提的。
  • 相关阅读:
    实验十四
    2
    解一元二次方程
    第一题
    输入四个人的年龄和姓名,排序后,按年龄,从小到大输出人员年龄及其姓名
    实验九
    实验8数组2 1.程序调试
    实验七4编写程序,输入一批学生的成绩,遇0或负数则输入结束,要求统计并输出优秀(大于85)、通过(60~84)和不及格(小于60)的学生人数。
    实验10 指针2
    作业4
  • 原文地址:https://www.cnblogs.com/subtract/p/7139843.html
Copyright © 2011-2022 走看看