浓缩解读前端系列书籍

浓缩解读《JavaScript设计模式与开发实践》②

2017-01-03  本文已影响313人  梁同学de自言自语

this、call和apply

QQ图片20170103163230.jpg

2.1 this

2.1.1 this的指向
var object = {
    str : "object str",
    print : function(){
        return this.str;
    }
};
console.log(object.print());
var str = "global"; //全局变量str
var object = {
    //对象属性str
    str : "object str",
    print : function(){
        return this.str;
    }
};
//将对象方法赋值给全局函数
var fn = object.print;
console.log(fn());
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <!-- DOM节点的ID属性 -->
        <input id="btn_id" type="button" value="click" />
        <script type="text/javascript">
            //全局id
            var id = "global_id";
            document.getElementById('btn_id').onclick = function(){
                //以对象的方法执行,此时this指向DOM对象,输出"div_id"
                console.log(this.id);
                //声明一个回调函数
                var callback = function(){
                    console.log(this.id);
                }
                //dosomething之后
                //由于以普通函数的方式执行,所以输出"global_id"
                callback();
            };
        </script>
    </body>
</html>
var Person = function(){
    this.str = "person str";
};
var person1 = new Person();
console.log(person1.str);    //输出“person str”
var Person = function(){
    this.str = "person str";
    return {
        this.str = "new person str";
    }
};
var person1 = new Person();
console.log(person1.str);   //输出"new person str"
var str = "global"; //全局变量str
var object1 = {
    str : "object1 str",
    print : function(){
        return this.str;
    }
};
var object2 = {
    str : "object2 str"
};
console.log(object1.print());   //输出"object1 str"
//可以理解成,通过object2对象来执行object1.print()方法。所以this指向的是object2对象,输出"object2 str"
console.log(object1.print.call(object2));
2.1.2 this丢失的情况
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <!-- DOM节点的ID属性 -->
        <input id="btn_id" type="button" value="click" />
        <script type="text/javascript">
            /*
             * 问题示例 
             */
            //将getElementById赋值给getId方法
            var getId = doc'ument.getElementById;
            getId("btn_id");'
            //控制台报错"Uncaught TypeError: Illegal invocation"
            
            /*
             * 示例修改
             */
            //这是因为getElementById()方法内部实现中用到了this了,本来默认this是指向ducument对象的,当做普通函数执行后,this指向就指向了window对象
            //修改:用getId方法包装一层,返回的是通过ducumet对象执行的getElementById()方法的结果
            var getId = function(id){
                return document.getElementById(id);
            };
            getId('btn_id');
        </script>
    </body>
</html>

2.2 call、apply和bind

2.2.1 call
//全局变量
var name = "window";
//公共的执行函数
function print(label){
    console.log(label + ":" + this.name);
}
//对象1
var person1 = {
    name : "Grubby"
};
//对象2
var person2 = {
    name : "Moon"
};print.call(this,"global");    //输出"global:window"
print.call(person1,"person1");  //输出"person1:Grubby"
print.call(person2,"person2");  //输出"person2:Moon"
2.2.2 apply
print.apply(this,["global"]);   //输出"global:window"
print.apply(person1,["person1"]);   //输出"person1:Grubby"
print.apply(person2,["person2"])    //输出"person2:Moon"
//两者的区别
/*
fn.call(obj, arg1, arg2, arg3...);
fn.apply(obj, [arg1, arg2, arg3...]);
*/
2.2.3 bind
//不出所料,输出"person1:Grubby"
var printForPerson1 = print.bind(person1);
printForPerson1("person1");
//输出"person2:Moon",绑定的时候传参和执行的时候传参都可以
var printForPerson2 = print.bind(person2,"person2");
printForPerson2();
//printForPerson1()中的this依据被绑定,纵使以person2.print()方法的方式执行,依然输出person1的name
person2.print = printForPerson1;
person2.print("person2");
2.2.3 用途
//Person构造函数,可以指定name
var Person = function(name){
    this.name = name;
};
//Student构造函数
var Student = function(){
    Person.apply(this,arguments);   //借用Person的构造函数
};
//为学生添加一个说出自己名字的方法
Student.prototype.sayName = function(){
    return this.name;
};
//实例化一个William学生
var student1 = new Student("William");
//虽然学生本身没有name属性,但是最终输出 "William"
console.log(student1.sayName());
var arr = [45,88,634,22,436,879];
var maxNum = Math.max.apply(Math, arr);
console.log(maxNum);
var minNum = Math.min.call(Math,45,88,634,22,436,879);
console.log(minNum);
var arr1 = [1,2,3];
var arr2 = [4,5,6];
[].push.apply(arr1, arr2);
console.log(arr1);
//输出: [1, 2, 3, 4, 5, 6]
上一篇 下一篇

猜你喜欢

热点阅读