问答详情
源自:5-2 圣诞雪橇

请问这里的this指什么?

http://img.mukewang.com/59b78f40000101c603830061.jpg

我已经理解了next("左运动参数")(马车开始向左运动).then("转向参数")(马车转向).then("右运动参数")(马车开始向右运动).then()(马车停止)这种方式。

  1. 请问这里的1,2,3号this分别指的是什么?

  2. 这里的逻辑怎么样的?如果让我写,我怎么知道这样去写,因为这里很不符合初学者思维习惯。

http://img.mukewang.com/59b790a40001874e03590040.jpg

  1. 这里的callback干什么用?

http://img.mukewang.com/59b790c300010c0e02000021.jpg

  1. 这里的this为什么要存到that去?

  2. 如果不用that保存this,那么this的引用会在哪被更改?



提问者:superhuman进化中 2017-09-12 15:48

个回答

  • FloatingShuYin
    2017-12-27 18:35:36
    已采纳

    2楼说的不错.

    我补充几点


    先说下apply()函数

    var add = function(a,b){
        return a + b;
    }
    var sub = function(a,b){
        return a - b;
    }
    
    var result = add.apply(sub,[8,1]);
    var result_1 = sub.apply(add,[8,1]);
    console.log(result); // 9
    console.log(result_1); // 7
    
    apply()是函数对象的一个方法,
    它的作用是改变函数的调用对象,
    它的第一个参数就表示改变后的调用这个函数的对象。

    而第一个和第二个this是指向globalwindow对象

    第三个this指向的是使用new调用构造函数pageA 实例化的对象

    关于 this 关键字 参考此链接

    http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html


    我们分析一下var next = function(){...}这个函数

    var next = function(){
       return this.next.apply(this,arguments);
    }.bind(this)


     第一个和第二个thisnext()函数的内部

    而第三个this不在next()的内部,而是属于pageA.prototype.run = function(callback){...}这个函数内部了.

    next()函数是全局对象global或window的方法,所以在next()函数内部的this就是指向他们了

    pageA.prototype.run = function(callback){...}这个函数内部的this是如下传递过来的

    new pageA($pageA);
    function pageA (element) {
        // this 指向pageA的实例对象
        //根元素
        this.$root = element;
        //小男孩
        this.$boy = element.find(".chs-boy");
        // 执行pageA的实例对象的run方法
        this.run();
    }

    如果我们给这个实例对象命个名

    var something = new pageA($pageA);

    那么第三个this就是由

    this.run(); 传递过来的something对象了


    我们再看bind()函数

    function add(a,b){    
        return a + b;
    }
    var a = 3;
    var b = 4;
    var newFoo = add.bind(this,a, b); 
    a = 6;
    b = 7;
    console.log(newFoo());  // 7
    console.log(this.a);  // 6
    console.log(this.b); // 7

    由此,我们可以得出结论

    bind()函数 绑定的是参数的值,而不是实际变量的值。


    再看这个例子

    this.num = 9; 
    
    var module = {  
    num: 81, 
    getNum: function() { return this.num;}
    }
    
     
    module.getNum(); // 81
    
    var getNum = module.getNum;
    getNum(); // 9, 因为在这个例子中,"this"指向全局对象
    
    // 创建一个'this'绑定到module的函数
    var boundGetNum = getNum.bind(module);
    
    boundGetNum();  // 81

    由此,我们可以得出结论

    bind()函数 改变了this的指向



    综上

    我们完全可以这样写

    // 给pageA添加run方法
    pageA.prototype.run = function(){
    
        // 存储当前上下文对象: pageA的实例对象
        var that = this;
        
        // 定义next方法 注意:此处不是pageA的next方法
        // 而是是pageA的run方法里面的next方法.
        var next = function(){
            return this.next.apply(this,arguments)
            // 注意 这里不写this 写的是that 意图更明显
        }.bind(that)
        
        // 这里调用的就是上面声明的next方法
        // 注意 上面用var声明的next()是没有定义参数的
        // 但是用了 arguments 这个关键字取得了传入的参数
        next({
            "time": 10000,
            "style": {
                "top": "4rem",
                "right": "16rem",
                "scale": "1.2"
            }
        })
        .then(function() {
           return next({
                "time":500,
                "style": {
                   "rotateY" : "-180",
                   "scale": "1.5"
                }
            })
        })    
        .then(function() {
            return next({
                "time": 7000,
                "style": {
                    "top"   :"7.8rem",
                    "right" : "1.2rem"
                }
            })
        })
        .then(function(){
            that.stopWalk();
        })  
    }

    目前的情况也可以这样写

     // 给pageA添加run方法
    pageA.prototype.run = function(){
        this.next({
            "time": 10000,
            "style": {
                "top": "4rem",
                "right": "16rem",
                "scale": "1.2"
            }
        })
        .then(function() {
           return this.next({
                "time":500,
                "style": {
                   "rotateY" : "-180",
                   "scale": "1.5"
                }
            })
        })    
        .then(function() {
            return this.next({
                "time": 7000,
                "style": {
                    "top"   :"7.8rem",
                    "right" : "1.2rem"
                }
            })
        })
        .then(function(){
        // 注意: 此处不再是that
            this.stopWalk();
        })  
    }





  • FloatingShuYin
    2017-12-27 18:52:57

    再补充一下....

    突然发现有一点没说

    就是为什么要多此一举声明另一个next()函数,然后用apply()和bind()函数来将对象转移呢?

    我猜测啊,应该是避免异步导致的参数赋值混乱.我猜的哈

    总之这样写应该是有其作用的

    因为我听说过一句话:任何编程方面的问题,都可以通过添加一个中间件的方式得到解决.



  • FloatingShuYin
    2017-12-27 18:38:18

    再补充一下 callback 是回调函数 目前没用  删掉也没关系

    下节应该会用到

  • 慕移动9273061
    2017-09-28 11:11:38

    第三个this指向的是构造函数pageA new出的对象,也就是对象本身。

    第一个和第二个this本应指向window,但被bind改变了指向,所以也指向对象本身。