您的位置:奥门新浦京网址 > Wed前段 > 开发很疯狂,换个思路理解Javascript中的this

开发很疯狂,换个思路理解Javascript中的this

发布时间:2019-11-12 05:23编辑:Wed前段浏览(130)

    添加失败动画

    首先,更新update()方法:用hit_pipe()替换restart_rame()。

    JavaScript

    this.game.physics.overlap(this.bird, this.pipes, this.hit_pipe, null, this);

    1
    this.game.physics.overlap(this.bird, this.pipes, this.hit_pipe, null, this);

    然后我们来写一个hit_pipe()方法。

    JavaScript

    hit_pipe: function() { // If the bird has already hit a pipe, we have nothing to do if (this.bird.alive == false) return; // Set the alive property of the bird to false this.bird.alive = false; // Prevent new pipes from appearing this.game.time.events.remove(this.timer); // Go through all the pipes, and stop their movement this.pipes.forEachAlive(function(p){ p.body.velocity.x = 0; }, this); },

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    hit_pipe: function() {  
        // If the bird has already hit a pipe, we have nothing to do
        if (this.bird.alive == false)
            return;
     
        // Set the alive property of the bird to false
        this.bird.alive = false;
     
        // Prevent new pipes from appearing
        this.game.time.events.remove(this.timer);
     
        // Go through all the pipes, and stop their movement
        this.pipes.forEachAlive(function(p){
            p.body.velocity.x = 0;
        }, this);
    },

    最后,为了保证撞了管子的小鸟不诈尸,在jump()方法的最前面添加如下代码:

    JavaScript

    if (this.bird.alive == false) return;

    1
    2
    if (this.bird.alive == false)  
        return;

    动画效果添加完毕。

    从call方法开始

    call 方法允许切换函数执行的上下文环境(context),即 this 绑定的对象。

    大多数介绍 this 的文章中都会把 call 方法放到最后介绍,但此文我们要把 call 方法放在第一位介绍,并从 call 方法切入来研究 this ,因为 call 函数是显式绑定 this 的指向,我们来看看它如何模拟实现(不考虑传入 nullundefined 和原始值):

    Function.prototype.call = function(thisArg) { var context = thisArg; var arr = []; var result; context.fn = this; for (let i = 1, len = arguments.length; i < len; i++) { arr.push('arguments[' + i + ']'); } result = eval("context.fn(" + arr + ")"); delete context.fn; return result; }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Function.prototype.call = function(thisArg) {
        var context = thisArg;
        var arr = [];
        var result;
     
        context.fn = this;
     
        for (let i = 1, len = arguments.length; i < len; i++) {
            arr.push('arguments[' + i + ']');
        }
     
        result = eval("context.fn(" + arr + ")");
     
        delete context.fn;
     
        return result;
    }

    从以上代码我们可以看到,把调用 call 方法的函数作为第一个参数对象的方法,此时相当于把第一个参数对象作为函数执行的上下文环境,而 this 是指向函数执行的上下文环境的,因此 this 就指向了第一个参数对象,实现了 call 方法切换函数执行上下文环境的功能。

    关于作者:小谢

    图片 1

    懒懒的程序员~ 个人主页 · 我的文章 · 24 ·  

    图片 2

    关于作者:杨帅

    图片 3

    (新浪微博:@JAVA程序员杨帅) 个人主页 · 我的文章

    图片 4

    闭包中的this

    var x = 1; var foo = { x: 2, y: 3, getXY: function(){ (function(){ console.log("x:" + this.x); console.log("y:" + this.y); })(); } } foo.getXY();

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var x = 1;
    var foo = {
        x: 2,
        y: 3,
        getXY: function(){
            (function(){
                console.log("x:" + this.x);
                console.log("y:" + this.y);
            })();
        }
    }
    foo.getXY();

    这段代码的上下文如下图:图片 5

    这里需要注意的是,我们再研究函数中的 this 指向时,只需要关注 this 所在的函数是如何调用的, this 所在函数外的函数调用都是浮云,是不需要关注的。因此在所有的图示中,我们只需要关注红色框中的内容。

    因此这段代码我们关注的部分只有:

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

    1
    2
    3
    (function(){
        console.log(this.x);
    })();

    与普通函数调用一样,创建一个虚拟上下文对象,然后普通函数作为这个虚拟上下文对象的方法立即调用,匿名函数中的 this 也就指向了这个虚拟上下文。图片 6

    为啥做 JS 开发很疯狂???

    2016/06/08 · JavaScript · 2 评论 · 开发

    本文由 伯乐在线 - 小谢 翻译,cotton 校稿。未经许可,禁止转载!
    英文出处:sfioritto。欢迎加入翻译组。

    Web开发时很有趣的~但是Javascript确是……令人生畏的。

    Web开发中其他一切对你而言都是很简单的,但是当你深入探究Javascript的时候,就会有一种“众人皆醒你独醉”的感觉,好像你不知道其他人都知道的一些重要的基础知识内容,并且这些内容可以帮助你理解所有知识。

    事实是,的确如此,你遗漏了一些解决问题的重要片段。

    并且,前端开发确实已经进入了疯狂的状态了。

    不仅仅是你。

    拉过一把椅子,坐下来。是到开始写Javascript应用的时间了。

    第一步是搭建本地开发环境并跑通它。那么是使用 Gulp?还是 Grunt?等等,好……好像还有 NPM script!

    WebPACK?还是 Browserify? (羞涩的)Require.js?升级到 ES6?或者为你的项目添加 Babel 支持?

    BDD 还是常规的单元测试?应该使用什么断言框架?从命令行运行测试显然很棒,所以 PhantomJS 也是不错的选择?

    Angular 还是 React?还是 Ember?再或者 Backbone?

    你看了一些 React 文档,“Redux 是一种为 Javascript 应用提供的可预测状态的容器。”酷毙了!你肯定需要其中的一个。

    为什么构建 Javascript 应用会如此疯狂?!?

    让我来告诉你为什么这一切是如此疯狂。让我们从一个例子开始,后面会有漂亮的图片。

    这是 React 的“Hello, world!”应用。

    JavaScript

    // main.js var React = require('react'); var ReactDOM = require('react-dom'); ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') );

    1
    2
    3
    4
    5
    6
    7
    8
    // main.js
    var React = require('react');
    var ReactDOM = require('react-dom');
     
    ReactDOM.render(
      <h1>Hello, world!</h1>,
      document.getElementById('example')
      );

    Not quite done. 不止这些。

    Shell

    $ npm install --save react react-dom babelify babel-preset-react $ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js

    1
    2
    $ npm install --save react react-dom babelify babel-preset-react
    $ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js

    实际上这里还缺了几个步骤,例如安装 browserify,以及在你做好之后还要让它运行在网页上,因为这其实不会直接产生一个能有什么内容的网页。 ¯ (ツ)

    在完成这些之后,你最后还需要一个名为 bundle.js 的文件,这个文件包含新的 React Hello World 应用程序,这个程序有 19374 行代码。而你只需要安装 browserify、babelify 和 react-dom 即可,它们会帮你生成成千上万行的你不了解的代码,想想吧。

    所以基本上是像下面这样的:

    JavaScript

    Marc was almost ready to implement his "hello world" React app pic.twitter.com/ptdg4yteF1 — Thomas Fuchs (@thomasfuchs) March 12, 2016

    1
    2
    3
    Marc was almost ready to implement his "hello world" React app pic.twitter.com/ptdg4yteF1
    — Thomas Fuchs (@thomasfuchs) March 12, 2016
     

    好,下面就让我们用简单的 Javascipt 代码写一个 Hello World 应用。

    XHTML

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>Hello World</title> </head> <body> <div id="container"></div> <script> document.body.onload = function(){ var container = document.getElementById("container"); container.innerHTML = '<h1>"Hello, world!"</h1>'; } </script> </body> </html>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width" />
        <title>Hello World</title>
      </head>
     
      <body>
        <div id="container"></div>
        <script>
         document.body.onload = function(){
           var container = document.getElementById("container");
           container.innerHTML = '<h1>"Hello, world!"</h1>';
         }
        </script>
      </body>
      </html>

    这就成了。一共 18 行代码。你可以复制/粘贴到 index.html 文件中,双击把它加载到你的浏览器中。搞定。

    此时你肯定会说:“等等,React 能做的事情比你刚刚写的这个小玩意更多,并且你不可能用那种方式写一个 Javascript 应用!”(大多数情况下)你是对的,但你还需要走一小步才能理解为什么一切都疯了。

    下面是我承诺过的图片。

    图片 7

    绝大多数你开发的Javascript web应用程序,会落在钟形曲线中部的某个位置。一定会在中间部分,如果你从一个完整的 React 堆栈开始,那么从一开始你就过度设计了你的应用程序。

    这就是为什么一切都变得疯狂。其中的大多数工具你觉得是你解决问题所必须具备的,但是你一直没有碰到这样的问题,而且以后你永远也不会碰到

    同一张图片:

    图片 8

    因为在默认情况下,每个人都过度设计他们的应用,他们却意识不到这一点,使得 Javascript 的开发状态变得过于繁冗。

    你应该如何启动 Javascript 应用程序呢?是否应该使用一些类似 React 或 Angular 的工具?是否应该使用软件包管理器?如果你不这样做,你应该做什么?测试有必要吗?是否应该用 Javascript 生成标志?所有这些都是你应该好好问问自己的问题,在启动默认的庞大的技术堆栈之前。

    当你启动一个 Javascript 应用程序时,关键是要在钟形曲线上挑一个点,这个点刚好位于你认为这个应用最终可能会到达的复杂程度的前面。

    我不会撒谎,验证这一切需要经验。但是这里有一个不错的点可以让你启动大多数的 Javascript 应用程序:jQuery 加上客户端模板,以及用于连接和缩减产品文件超级简单的构建工具(假如你的后端架构还没有这样做的话)。

    如果你知道如何正确地构建 Javascript 应用程序,那么你就会开始懂得怎样、何时以及为什么使用框架或 npm/requir/webPack 或 ES6,什么时候编写测试,什么时候应该费心让你的测试本地运行,什么时候运行在浏览器中,所有这些问题都会搞定。

    有兴趣用你的 Javascript 开发知识填补那些空白?想要避免不堪重负的感觉?想要避免在这个开发过程中过度设计你的 Javascript 应用程序?那是我下个月将要专注讨论的内容,所以,敬请期待,在一两周后会有更多干货到来!

    打赏支持我翻译更多好文章,谢谢!

    打赏译者

    设置

    首先下载新的模板。其中包括了我们在上一个教程中完成的代码和一个新的音效文件。

    打开main.js,开始敲吧。

    参数中的this

    var x = 1; var foo = { x: 2, getX: function(){ console.log(this.x); } } setTimeout(foo.getX, 1000);

    1
    2
    3
    4
    5
    6
    7
    8
    var x = 1;
    var foo = {
        x: 2,
        getX: function(){
            console.log(this.x);
        }
    }
    setTimeout(foo.getX, 1000);

    函数参数是值传递的,因此上面代码等同于以下代码:

    var getX = function(){ console.log(this.x); }; setTimeout(getX, 1000);

    1
    2
    3
    4
    var getX = function(){
        console.log(this.x);
    };
    setTimeout(getX, 1000);

    然后我们又回到了普通函数调用的问题。

    打赏支持我翻译更多好文章,谢谢!

    任选一种支付方式

    图片 9 图片 10

    3 赞 4 收藏 2 评论

    添加飞行动画

    小鸟上下飞行的方式太单调了,我们来加一些特效,让它看起来有点儿游戏的样子。

    1.下降时角度转动速度放慢,直到特定值。
    2.上升时翻转角度。

    第一个任务很简单,我们只需要添加两行代码到update()方法。

    JavaScript

    if (this.bird.angle < 20) this.bird.angle += 1;

    1
    2
    if (this.bird.angle &lt; 20)  
        this.bird.angle += 1;

    第二步我们有两个选择,
    简单起见,我们可以只在jump()方法中添加

    JavaScript

    this.bird.angle = -20;

    1
    this.bird.angle = -20;

    但是这中角度的骤变看起来有点儿别扭。所以,我们还可以让角度有个变化的过程。我们可以用如下代码替换掉上面的。

    JavaScript

    // create an animation on the bird var animation = this.game.add.tween(this.bird); // Set the animation to change the angle of the sprite to -20° in 100 milliseconds animation.to({angle: -20}, 100); // And start the animation animation.start();

    1
    2
    3
    4
    5
    6
    7
    8
    // create an animation on the bird
    var animation = this.game.add.tween(this.bird);
     
    // Set the animation to change the angle of the sprite to -20° in 100 milliseconds
    animation.to({angle: -20}, 100);
     
    // And start the animation
    animation.start();

    也可以揉成一行代码:

    JavaScript

    this.game.add.tween(this.bird).to({angle: -20}, 100).start();

    1
    this.game.add.tween(this.bird).to({angle: -20}, 100).start();

    这样一来就差不多了,如果你现在测试一下游戏,你会发现小鸟的角度变化得并不自然。像左边的图,但是我们想要的是右图的效果。

    图片 11

    为了达到这个目的,我们要做的是改变小鸟的中心(anchor)。在create()方法中添加如下代码来改变中心(anchor)。

    JavaScript

    this.bird.anchor.setTo(-0.2, 0.5);

    1
    this.bird.anchor.setTo(-0.2, 0.5);

    现在测试一下游戏你就会发现已经好得多了。

    对象方法中的this

    在模拟 call 方法的时候,我们使用了对象方法来改变 this 的指向。调用对象中的方法时,会把对象作为方法的上下文环境来调用。

    既然 this 是指向执行函数的上下文环境的,那我们先来研究一下调用函数时的执行上下文情况。

    下面我门来看看调用对象方法时执行上下文是如何的:

    var foo = { x : 1, getX: function(){ console.log(this.x); } } foo.getX();

    1
    2
    3
    4
    5
    6
    7
    var foo = {
        x : 1,
        getX: function(){
            console.log(this.x);
        }
    }
    foo.getX();

    图片 12

    从上图中,我们可以看出getX方法的调用者的上下文是foo,因此getX方法中的 this 指向调用者上下文foo,转换成 call 方法为foo.getX.call(foo)

    下面我们把其他函数的调用方式都按调用对象方法的思路来转换。

    本文由奥门新浦京网址发布于Wed前段,转载请注明出处:开发很疯狂,换个思路理解Javascript中的this

    关键词: