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()方法未被修改为前提的。
  • 相关阅读:
    leetcode--Populating Next Right Pointers in Each Node II
    leetcode—Populating Next Right Pointers in Each Node
    Pascal's Triangle II
    leetcode—pascal triangle
    leetcode—triangle
    October 23rd, 2017 Week 43rd Monday
    October 22nd, 2017 Week 43rd Sunday
    October 21st 2017 Week 42nd Saturday
    October 20th 2017 Week 42nd Friday
    October 19th 2017 Week 42nd Thursday
  • 原文地址:https://www.cnblogs.com/subtract/p/7139843.html
Copyright © 2011-2022 走看看