質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • JavaScript

    19274questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    7749questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Ruby on Rails 4

    2520questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

  • CoffeeScript

    148questions

    CoffeeScriptはプログラミング言語です。シンタックスシュガーの導入により、JavaScriptのコードに変換された後動作します。JavaScriptに比べ、可読性と簡潔性が向上しています。

coffeescriptからjavascriptのコンパイルでreturnが一つ余計に表示されてしまう。

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,495

s.k

score 249

私がフォローしている方々でcoffeescriptタグを持つ人にリクエストを送りました!

前提・実現したいこと

処理速度、コードの複雑化を改善するためにjavascriptをcoffeescriptへ移行したい。
下記番号で言いますと、①=③になるように②のCoffeeScriptを修正したい。

javascriptでfacebookのような「続きを見る」機能を苦戦しながらもみなさんのご助力をいただき実装しました。この機能は複数ページに必要な機能でしたので、複数ファイルに同様のjsコードを記述しています。

しかし、
・同様のコードを書いているために無駄が多く見にくい。
・(これはご指摘を受けたのですが、)jsとrailsの接続をするという二度手間が生じる。

という問題がありますので、JavaScriptコードをCoffeeScriptコードに書き換えようと考えました。

発生している問題・エラーメッセージ

問題はこのエラーです。

ExecJS::RuntimeError in Page#index
Showing /home/ubuntu/workspace/app/views/layouts/application.html.erb where line #6 raised:

SyntaxError: [stdin]:4:19: reserved word 'function'


このエラーは調べたところ、
coffee内のコードミスということでしたので、

http://coffeescript.org/

で、一字一句確認したのですが、1点だけどうしてもうまくいきません。
・元のjavascriptコードよりも});が一つ少ない。

該当のソースコード

①【元のJavaScriptコード】
②【①のJavascriptコードを書き換えたCoffeeScriptコード】
③【http://coffeescript.org/で②のCoffeeScriptコードをコンパイルしたJavaScriptコード】

①【元のJavaScriptコード】

$(document).ready(function() {
    var showChar = 100;
    var ellipsestext = "...";
    var moretext = "more";
    var lesstext = "less";
    $('.more').each(function() {
        var content = $(this).html();

        if(content.length > showChar) {

            var c = content.substr(0, showChar);
            var h = content.substr(showChar, content.length - showChar);

            var html = c + '<span class="moreellipses">' + ellipsestext+ '&nbsp;</span><span class="morecontent"><span>' + h + '</span>&nbsp;&nbsp;<a href="" class="morelink">' + moretext + '</a></span>';

            $(this).html(html);
        }

    });

    $(".morelink").click(function(){
        if($(this).hasClass("less")) {
            $(this).removeClass("less");
            $(this).html(moretext);
        } else {
            $(this).addClass("less");
            $(this).html(lesstext);
        }
        $(this).parent().prev().toggle();
        $(this).prev().toggle();
        return false;
    });
}); ←③で足りない箇所

②【①のJavascriptコードを書き換えたCoffeeScriptコード】

$(document).ready ->
  showChar = 100
  ellipsestext = "..."
  moretext = "more"
  lesstext = "less"
  return

$('.more').each  -> 
        content = $(trim).$(this).html()

        if content.length > showChar

            c = content.substr 0, showChar
            h = content.substr showChar, content.length - showChar 

            html = c + '<span class="moreellipses">' + ellipsestext+ '&nbsp;</span><span class="morecontent"><span>' + h + '</span>&nbsp;&nbsp;<a href="" class="morelink">' + moretext + '</a></span>'

            $(this).html html
            return

$(".morelink").click ->
        if $(this).hasClass "less"
            $(this).removeClass "less"
            $(this).html moretext
            return
        else 
            $(this).addClass "less"
            $(this).html lesstext
            return

        $(this).parent().prev().toggle()
        $(this).prev().toggle()
        false

③【http://coffeescript.org/で②のCoffeeScriptコードをコンパイルしたJavaScriptコード】

$(document).ready(function() {
  var ellipsestext, lesstext, moretext, showChar;
  showChar = 100;
  ellipsestext = "...";
  moretext = "more";
  lesstext = "less";
});

$('.more').each(function() {
  var c, content, h, html;
  content = $(trim).$(this).html();
  if (content.length > showChar) {
    c = content.substr(0, showChar);
    h = content.substr(showChar, content.length - showChar);
    html = c + '<span class="moreellipses">' + ellipsestext + '&nbsp;</span><span class="morecontent"><span>' + h + '</span>&nbsp;&nbsp;<a href="" class="morelink">' + moretext + '</a></span>';
    $(this).html(html);
  }
});

$(".morelink").click(function() {
  if ($(this).hasClass("less")) {
    $(this).removeClass("less");
    $(this).html(moretext);
    return;
  } else {
    $(this).addClass("less");
    $(this).html(lesstext);
    return;
  }
  $(this).parent().prev().toggle();
  $(this).prev().toggle();
  return false;
}); ←下にもう一つ});が入るはず。

何卒、ご助言お願い致します。

情報追加部分

④【現時点のCoffeeScriptコード】

$ ->
  showChar = 100
  ellipsestext = "..."
  moretext = "more"
  lesstext = "less"

  $('.more').each ->
    content = $(@).html()

    if content.length > showChar

      c = content.substr 0, showChar
      h = content.substr showChar, content.length - showChar

      html = """ #{c}
      <span class="moreellipses">
      #{ellipsestext}&nbsp;
      </span>
      <span class="morecontent">
        <span>#{h}</span>&nbsp;&nbsp;
        <a href="" class="morelink">#{moretext}</a>
      </span>"""

      $(@).html html

  $(".morelink").click ->
    if $(@).hasClass "less"
       $(@).removeClass "less"
       $(@).html moretext
    else 
       $(@).addClass "less"
       $(@).html lesstext

    $(@).parent().prev().toggle()
    $(@).prev().toggle()
    return false;

⑤【④をコンパイルしたJavaScriptコード】

$(function() {
  var ellipsestext, lesstext, moretext, showChar;
  showChar = 100;
  ellipsestext = "...";
  moretext = "more";
  lesstext = "less";
  $('.more').each(function() {
    var c, content, h, html;
    content = $(this).html();
    if (content.length > showChar) {
      c = content.substr(0, showChar);
      h = content.substr(showChar, content.length - showChar);
      html = " " + c + "\n<span class=\"moreellipses\">\n" + ellipsestext + "&nbsp;\n</span>\n<span class=\"morecontent\">\n  <span>" + h + "</span>&nbsp;&nbsp;\n  <a href=\"\" class=\"morelink\">" + moretext + "</a>\n</span>";
      return $(this).html(html);
    }
  });
  return $(".morelink").click(function() { ←どうしてもこのreturnを消したい。
    if ($(this).hasClass("less")) {
      $(this).removeClass("less");
      $(this).html(moretext);
    } else {
      $(this).addClass("less");
      $(this).html(lesstext);
    }
    $(this).parent().prev().toggle();
    $(this).prev().toggle();
    return false;
  });
});

⑥【実現したいJavaScriptコード】

$(document).ready(function() {
  var ellipsestext, lesstext, moretext, showChar;
  showChar = 100;
  ellipsestext = "...";
  moretext = "more";
  lesstext = "less"; ←⑤でreturnをjsコードで追加したことで、coffeeではreturnが消えました。
});

$('.more').each(function() {
  var c, content, h, html;
  content = $(trim).$(this).html();
  if (content.length > showChar) {
    c = content.substr(0, showChar);
    h = content.substr(showChar, content.length - showChar);
    html = c + '<span class="moreellipses">' + ellipsestext + '&nbsp;</span><span class="morecontent"><span>' + h + '</span>&nbsp;&nbsp;<a href="" class="morelink">' + moretext + '</a></span>';
    $(this).html(html);
  }
});

$(".morelink").click(function() { 
  if ($(this).hasClass("less")) {
    $(this).removeClass("less");
    $(this).html(moretext);
  } else {
    $(this).addClass("less");
    $(this).html(lesstext);
  }
  $(this).parent().prev().toggle();
  $(this).prev().toggle();
  return false;
 });
});
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+5

参考情報

次の例を見てください。

$ cat a.coffee
foo = (x) ->
  console.log x

$ coffee -pb a.coffee
var foo;

foo = function(x) {
  return console.log(x);
};
$ cat b.coffee
foo = (x) ->
  console.log x
  return

$ coffee -pb b.coffee 
var foo;

foo = function(x) {
  console.log(x);
};

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/04 11:27 編集

    katoyさん

    ありがとうございます!
    記事みました。

    すべてを理解できはしなかったのですが、
    ざっくりいうと、値を返さない関数にはreturnをつける。
    returnをつけると無駄なコードを省き最適化されるといった具合でしょうか…

    キャンセル

checkベストアンサー

+4

coffeeはsyntaxシュガーで
$(document).readyは

$ ->


とかけます。この時indentはスペース二つでブロックスコープの範囲を設定します。なので関数の中に含めたいコードは全て
関数のindentからスペース二つずらす必要があります。
よってreadyにすべて含めたければ$('.more')と$(".morelink")およびその中身のindentをずらす必要があります。

慣れないうちは

$ ->
  console.log('test')


などから始めちょっとずつコードを付けたしながらやるのがいいと思います。

以下は補足情報になります。

returnは書かなくても関数のなかで最終評価された値を勝手に返しますが,明示的に付けても構いません。
returnで返り値を指定しないとvoid型の関数になるだけです。
単独の@はthisのエイリアスなのでthisの部分は@で書いたほうが見通し良くなります。

また,sprocketsを使っているとすべてのページでcoffeescriptが発火してしまうので特定のviewのみで使いたい場合はviewのbody内のdomのどこかに任意のid(ここではpage-idとします)を振っておき,

$ ->
  if $('#page-id').length>0
    console.log('triggered in this page')

などとすることが多いです。
またcoffescriptは文字列展開とヒアドキュメント("""で囲む)(こちらはES6(''で囲む)でも使えるようになりましたが)が使えるので

html = c + '<span class="moreellipses">' + ellipsestext + '&nbsp;</span><span class="morecontent"><span>' + h + '</span>&nbsp;&nbsp;<a href="" class="morelink">' + moretext + '</a></span>'


html = """ #{c}
<span class="moreellipses">
  #{ellipsestext}&nbsp;
</span>
<span class="morecontent">
  <span>#{h}</span>&nbsp;&nbsp;
  <a href="" class="morelink">#{moretext}</a>
</span>"""

と書くと見通しが良くなると思います(compileしてないのでerror履いたら調べて補間してもらえうと)。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/02 12:34

    tkowさん

    返信ありがとうございます!
    tkowさんに教えていただいたコードをCooffeeScript(質問文の④)に書きました。
    かなりコードがスッキリして見やすいです。

    ただ、試行錯誤してもどうしてもreturnが一つ多く表示されてしまいます。(質問文の⑤)
    returnがある文の上か下のコードどちらに原因があるかご指摘いただけないでしょうか…

    キャンセル

  • 2016/11/02 12:49 編集

    tkowさん

    ④のコードをそのまま、アプリファイルで実行したら正常に動きました!
    コンパイルしたときにreturnが余計にあるのにこれは一体…

    キャンセル

  • 2016/11/02 13:05 編集

    coffeeScriptはそういう風にbuildされるものです。
    javascriptのコードは汚くなったり冗長になりがちなのでcoffeeで管理してjsに自動でトランスパイルするような仕組みを作るものです。なので変換先のjavascriptが綺麗に生成されることを考慮していません。(元々プロダクトを作るときは結局uglifyするはずなのでコンパイル先の綺麗さは気にしなくていいという前提があります。)
    return の評価は戻り値が評価されてから起きるので,実行時に戻り値を受け取る変数がなくても問題は起きません。なのでこのように作成されるようになっています。
    どうしても治したい場合はreturn false;の下に$(".morelink").clickの同じindentでreturn を入れてください。

    キャンセル

  • 2016/11/02 13:12

    開発でjavascriptしか使えない方を考慮している感じですかね。
    そうするとcoffeeの導入は良くないかもしれません。
    typescriptはほぼes6そのままのコードを書けるのでこちらの方がいいと思います。

    キャンセル

  • 2016/11/02 13:26

    returnの件、解決いたしました!
    ありがとうございます。

    いっぱいあるのですね…
    typescript調べてみます^o^

    助かりました。
    引き続き開発を続けたいと思います!

    キャンセル

+4

なにやら色々混乱しているようですが…ひとつひとつ指摘していきます。

CoffeeScriptはインデントがブロックになる。

f ->
  a()

  b()


f ->
  a()

b()


は違います。上ではb()はfの引数の無名関数の中に含まれていますが、下ではb()は無名関数の外側です。質問の①は上の構成である(全て関数の中にある)のに、②ではインデントされていないところがあるため、下の構成になっています。これでは同じになりません。JavaScriptをCoffeeScriptにする場合は、ブロックを構成する{}の対応通りに、インデントと逆インデントをしなければなりません。綺麗にインデントを整形しているJavaScriptであれば、そのJavaScriptとCoffeeScriptのインデントは同じになるはずです。しかし、①と②では$('.more').each ...$(".morelink").clickのインデントが同じではありません。だからブロックが全体で包まれず、最後の方のブロックを閉じる分が少なく見えるのです。

CoffeeScriptでは最後の式を返す。

JavaScriptではreturn文がない場合、最後にreturn;があると見なされ、returnで式が指定されていない場合はundefinedを返します。逆に言うと、最後のreturn;は省略可能と言うことです。(他の言語と違って、JavaScriptでは何も返さない関数を作ることはできません)

対して、CoffeeScriptでは、最後に評価された式の結果を返します。つまり、最後が【何かの式】という形であれば、return 【何かの式】のようになっていると見なします。なお、CoffeeScriptではifやwhile等も文ではなく式ですので、必ず何かしらの値を返しますので、同じくreturnが付くことになります(ただし、式として評価するためにやや複雑なコードに変換されます)。

もし、JavaScriptでreturnを省略したときの動作と同じにしたいというのであれば、CoffeeScriptでは逆にreturn(ただし、何も指定しない)を省略せずに書く必要があります。つまり、CoffeeScriptは最後の式の結果を返す場合はreturnを省略でき、JavaScriptではundefinedを返す場合のみreturnを省略できるという逆の動作になっていると言うことです。

なお、CoffeeScriptのundefined変数はvoid 0であり、その結果としてundefinedになるだけです。JavaScriptにおいてreturn;return undefined;が同じではないのと同じく、CoffeeScriptではreturnreturn undefindは同じではありませんが、結果だけを見ると、CoffeeScriptは両方ともundefindを返すという同じ動作になります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/02 14:20

    raccyさん

    おお…
    なるほど…

    JavaScriptとCoffeeScriptの違いの一つにインデントの指定があるのはわかったのですが、
    具体的にインデントがどのように機能しているのかは理解し切れていませんでした。

    returnに関しても同じです。
    すっきりとした気分になりました。

    ありがとうございます(^^)

    キャンセル

+3

$(document).ready は下記コードで完結している為、SyntaxError は発生しないように読めます。

$(document).ready(function() {
  var ellipsestext, lesstext, moretext, showChar;
  showChar = 100;
  ellipsestext = "...";
  moretext = "more";
  lesstext = "less";
});

CoffeeScript に詳しくありませんが、インデントに問題があるのではないでしょうか。

Re: s.k さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/01 19:14

    think49さん

    先程はありがとうございました!
    今、確認してみます!

    キャンセル

  • 2016/11/01 19:20

    本題とは関係ありませんが、$(".morelink").click(function() { 内の if, else でなぜ return しているのでしょうか。
    元のJavaScriptコードにはない命令でそれがある為に $(this).parent().prev().toggle(); 以降のコードが絶対に通過しない文になってしまっています。

    キャンセル

  • 2016/11/01 19:36 編集

    追記をしました。
    最初にjsコードを修正した際に、returnがあちこちにありました。
    調べたところ、returnがないところにはreturnのみを追加して明示的に示さなければならないと書いてあったので、いらぬところにreturnが書かれているという状況です…


    returnが修正したコードに存在していても最終的にcoffeescriptに出力されているコードが元のjsコードと一致していれば問題はないのかなと考えました!
    それと、そもそも、

    $(document).ready(function() {
    var ellipsestext, lesstext, moretext, showChar;
    showChar = 100;
    ellipsestext = "...";
    moretext = "more";
    lesstext = "less";
    });

    この文に});はついていないので、これもエラーだと思います。
    見逃していました…

    キャンセル

  • 2016/11/01 19:55

    すみませんが、コードが分散していて現状のまとめとなるコードが想像できません。
    修正版を追記するなら部分的ではなく、全て追記して下さい。下記3つがあれば十分です。
    - 元々のJavaScriptコード
    - CoffeeScriptコード
    - コンパイル後のJavaScriptコード

    「①【元のjsコード】」が基本でCoffeeScriptでコンパイルしたら「①【元のjsコード】」が出力される動作を期待している、という理解でいいのでしょうか。
    CoffeeScriptはインデントによって対応する括弧を決める言語のようです。
    ということは、$('.more').each, $(".morelink").click のインデントを修正する必要がありますね。

    キャンセル

  • 2016/11/01 20:20 編集

    think49さん、失礼しました!
    気を付けます。

    - 元々のJavaScriptコード 
    →①です。
    - CoffeeScriptコード
    →②です。
    - コンパイル後のJavaScriptコード
    →③です。

    ④~⑥は①~③の具体的なエラー箇所と解決策のコードを書いたつもりです…
    わかりづらいですね。

    コード左上に言語も追加します。

    ‐‐「①【元のjsコード】」が基本でCoffeeScriptでコンパイルしたら「①【元のjsコード】」が出力される動作を期待している、という理解でいいのでしょうか。

    はい!そうです。ですので、①=③という形にしたいです。

    ‐‐CoffeeScriptはインデントによって対応する括弧を決める言語のようです。
    ということは、$('.more').each, $(".morelink").click のインデントを修正する必要がありますね

    →そうなんですか。今試してみます!


    わかりづらいところがあれば全て言ってください!
    お手数おかけします。

    自分でも質問文を修正し直してみます

    キャンセル

  • 2016/11/01 20:24 編集

    上記コメントの
    - 元々のJavaScriptコード
    - CoffeeScriptコード
    - コンパイル後のJavaScriptコード
    ですが、間違えて伝えてしまいましたので修正しました。

    少々お待ちください。
    質問文も修正します。

    キャンセル

  • 2016/11/01 20:39

    質問文の修正終了しました!

    キャンセル

  • 2016/11/01 20:52

    return は余計な位置でつけなくて良いようです。やはり、インデントが問題っぽいですね。

    キャンセル

  • 2016/11/01 21:37

    ありがとうございます!
    returnを消して、インデント確かめてみます!

    キャンセル

同じタグがついた質問を見る

  • JavaScript

    19274questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    7749questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Ruby on Rails 4

    2520questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

  • CoffeeScript

    148questions

    CoffeeScriptはプログラミング言語です。シンタックスシュガーの導入により、JavaScriptのコードに変換された後動作します。JavaScriptに比べ、可読性と簡潔性が向上しています。