■ Light of the City wav版 ■ Light of the City Apple lossless版
]]>音楽が好きな人はこの3曲は一枚1,404円で買っても満足すると思う。色んな楽曲聴いていたけどセンスは良いと思う。
]]>
var pre = "kokia";
// re = "kokia1"
var re = _.uniqueId( pre );
// re2 = "kokia2"
var re2 = _.uniqueId( pre );
var idCounter = 0;
_.uniqueId = function(prefix) {
var id = ++idCounter + "";
// 引数がある時は、引数 + id で返す。
return prefix ? prefix + id : id;
};
var str = "kokia & 上野洋子";
// "Kokia & 上野洋子"
console.log(_.unescape(str) );
_.unescape = createEscaper(unescapeMap);
// _.invert() は key値を値に値をkey値に入れ替える関数。
var unescapeMap = _.invert(escapeMap);
var escapeMap = {
"&" : "&",
"<" : "&lt;",
">" : "&gt;",
'"' : "&quot;",
"'" : "x27;",
"`" : "x60;"
};
var createEscaper = function(map) {
var escaper = function(match) {
// return escapeMap[match]
return map[match];
};
var source = "(?:" + _.keys(map).join("|") + ")";
// testRegexp = /(?:&amp;|&lt;|&gt;|&quot;|x27;|x60;)/;
var testRegexp = RegExp(source);
// replaceRegexp = /(?:&amp;|&lt;|&gt;|&quot;|x27;|x60;)/g;
var replaceRegexp = RegExp(source, "g");
// _.unescape() の引数はこの返される関数の引数。
return function(string) {
string = string == null ? "" : "" + string;
// testRegexp.test(string); が false なら _.unescape() の引数は何もされずに返る。
// testRegexp.test(string); が true なら マッチした文字が escaper() に渡されマッチした文字が置き換えられる。
// CMS tool のエラーのためリプレイスの表記少し変えています。
return testRegexp.test(string) ? string.r(e)place(replaceRegexp, escaper) : string;
};
};
function call( txt ){
console.log( txt );
};
// 6回コンソールに表示される。
var re = _.times( 6, call );
_.times = function(n, iteratee, context){
// 引数「n」と0のどちらか大きい数の length を持つ配列を作成。
var accum = Array(Math.max(0, n));
// context = undefined の場合は そのままの iteratee が返る。
iteratee = optimizeCb( iteratee, context, 1);
// 第2引数に「 i 」を渡して実行した結果を accum 配列に入れる。
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
// 結果を入れた配列を返す。
return accum;
};
var span_template = _.template("<span><%- span_val %></span>");
// re = "<span>TM Network : CAROL</span>";
var re = span_template( {span_val: "TM Network : CAROL"} );
_.templateSettings = {
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%=([\s\S]+?)%>/g,
escape : /<%-([\s\S]+?)%>/g
};
var noMatch = /(.)^/;
var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
return '\\' + escapes[match];
};
_.template = function(text, settings, oldSettings) {
// 第2引数が null で第3引数がある場合。
if (!settings && oldSettings) settings = oldSettings;
// 第2引数と「_.templateSettings」に含まれている全てのプロパティを空のObjectにコピー、それが settings になる。
settings = _.defaults({}, settings, _.templateSettings);
// (settings.escape || noMatch).source = <%-([\s\S]+?)%>;
var matcher = RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join("|") + "|$", "g");
// matcher = /<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$/g;
var index = 0;
var source = "__p+='";
// source に テンプレートタグをエスケープ処理して文字列連結する。
// CMS tool のエラーでリプレイスの綴りを変えています。
text.r(e)place(matcher, function(match, escape, interpolate, evaluate, offset) {
// 上の使用例だと1回目は match = <%- span_val %>; escape = span_val; interpolate = undefined; evaluate = undefined; offset = 6;
// 2回目は match = ; escape = undefined; interpolate = undefined; evaluate = undefined; offset = 28;
// エラーになる" u2028 " などをエスケープ処理する。
source += text.slice(index, offset).r(e)place(escaper, escapeChar);
index = offset + match.length;
// source にマッチした文字の結果を文字列連結する。
if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
} else if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} else if (evaluate) {
source += "'\n" + evaluate + "\n__p+='";
}
return match;
});
source += "'\n";
// 上の使用例だと
source = __p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';
// settings.variable は第2引数で意図的にセットしないと入らないはずなので、ここの If 文は実行される。
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
// source = with(obj||{}){
__p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';
}
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + 'return __p;\n';
// source = var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';
}
return __p;
// テンプレートを設定する関数を新規作成。
try {
var render = new Function(settings.variable || 'obj', '_', source);
} catch (e) {
e.source = source;
throw e;
}
// render = function anonymous(obj, _) {
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';
}
return __p;
}
var template = function(data) {
return render.call(this, data, _);
};
var argument = settings.variable || 'obj';
template.source = 'function(' + argument + '){\n' + source + '}';
// template.source = function(obj){
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<span>'+
((__t=( span_val ))==null?'':_.escape(__t))+
'</span>';
}
return __p;
}
// render関数が返される。
return template;
};
// 返されるrender関数を解析。
render = function (obj, _) {
// 解析するため、_関数の外で関数を実行しているので少し改造。_を定義。
var _ = window._;
var __t,
__p = "",
__j = Array.prototype.join,
// この「print」の定義の文がなくても このrender関数は動く。
print = function(){ __p+=__j.call( arguments,"" ); };
// with(obj){ ttt = span_val; } と書いた場合は ttt = TM Network : CAROL;
// with構文の独特な使い方。
with(obj||{}){
__p+= "<span>" + ( (__t = ( span_val ) ) == null ? "" : _.escape(__t) ) + "</span>";
}
return __p;
}
// re = "<span>TM Network : CAROL</span>";
var re = render( { span_val : "TM Network : CAROL" } );
// アラート表示で[ 2, 200 ]が表示される。
var re = _.chain([1,2,3,200])
.filter(function(num) { return num % 2 == 0; })
.tap(alert)
.map(function(num) { return num * num })
.value();
_.tap = function(obj, interceptor) {
// 引数「obj」は_.tap()の前の結果から渡される Object か array。
// 引数「interceptor」は_.tap()関数の引数。上の例だと「alert」
interceptor(obj);
return obj;
};
var obj = {
author : "TM Network",
works : "CAROL",
works2 : "Dress",
works4 : "Self Control",
works5 : "Rhythm Red",
works6 : "Expo",
works7 : "Twinkle Night",
works8 : "GORILLA",
funks : function(){
return _.functions( this );
}
};
// re = [ "funks" ];
var re = _.result( obj, "funks" );
// re2 = "CAROL";
var re2 = _.result( obj, "works" );
_.result = function(object, property, fallback) {
// 第1引数が null なら value = undefined;
var value = object == null ? void 0 : object[property];
if (value === void 0) {
// 第1引数が null なら第3引数が返される。
value = fallback;
}
// value が関数なら value.call( object );
return _.isFunction(value) ? value.call(object) : value;
};
var obj = {
music : "弦楽四重奏によるドラゴンクエスト",
author : "すぎやまこういち"
}
// "弦楽四重奏によるドラゴンクエスト";
var re = _.propertyOf( obj )( "music" );
_.propertyOf = function(obj) {
// 引数が null だったら function(){}; を返す。
return obj == null ? function(){} : function(key) {
return obj[key];
};
};
var obj = {
works : "飛行夢",
works2 : "遠い音楽",
works3 : "私は羊",
works4 : "桜",
works5 : "moon years"
};
// re = { works2: "遠い音楽", works5: "moon years" };
var re = _.pick( obj, "works2", "works5" );
_.pick = function(object, oiteratee, context) {
var result = {}, obj = object, iteratee, keys;
// 第1引数が null だったら
if (obj == null) return result;
// 第2引数が関数だったら
if (_.isFunction(oiteratee)) {
// 第1引数のkey値をまとめた配列を作成。
keys = _.allKeys(obj);
// 第2引数が関数で context = undefined ならそのまま。
iteratee = optimizeCb(oiteratee, context);
} else {
// 第2引数以降が配列としてまとめられる。
keys = flatten(arguments, false, false, 1);
// 受け取った「Object」に受け取ったkey値があるかの真偽値を返す関数。
iteratee = function(value, key, obj) { return key in obj; };
// 第1引数をオブジェクトラッパーで包む。
obj = Object(obj);
}
// 第2引数で指定されたkey値(か関数)とその値で構成されたObjectを作成するforループ。
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
var value = obj[key];
if (iteratee(value, key, obj)) result[key] = value;
}
// 結果のObjectを返す。
return result;
};
_.mixin({
// 新規メソッド「capitalize」を定義。
capitalize: function(string) {
return string.charAt(0).toUpperCase() + string.toLowerCase();
}
});
// re = "Kkokia";
var re = _("KOKIA").capitalize();
// re2 = "Kkokia";
var re2 = _.capitalize("KOKIA");
// _.mixin() の内部で最後に呼ばれる関数。
var result = function(instance, obj) {
// 「instance._chain」が ture の時、_内にラップしてインスタンスを返す。
return instance._chain ? _(obj).chain() : obj;
};
_.mixin = function(obj) {
// 引数「obj」の全メソッド名の配列に_.each()でUnderscore内部にメソッドを追加する関数を適用。
_.each(_.functions(obj), function(name) {
// 受け取ったメソッドを_[メソッド名]として追加。
var func = _[name] = obj[name];
_.prototype[name] = function() {
// args は_() 時の引数。
var args = [this._wrapped];
// arguments は上の例だと_.capitalize()の引数。
push.apply(args, arguments);
// _.prototype[name]() を実行した時は result() 関数を適用して返す。
return result(this, func.apply(_, args));
};
// _.prototype[name]() の定義終了。
});
};
var obj = {
title : "遠い音楽",
year : 1990,
author : "Zabadak"
};
// re = [ ["title","遠い音楽"], ["year",1990], ["author","Zabadak"] ];
var re = _.pairs( obj );
_.pairs = function(obj) {
// 引数のkey値を抽出した配列を作る。
var keys = _.keys(obj);
// key配列の長さを抽出。
var length = keys.length;
// 結果用の空の配列を作成する。
var pairs = Array(length);
// key値とその値を入れた配列を作るforループ。
for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]];
}
return pairs;
};
var obj = {
works : "飛行夢",
works2 : "遠い音楽",
works3 : "私は羊",
works4 : "桜",
works5 : "moon years"
};
// re = { works: "飛行夢", works3: "私は羊", works4: "桜" };
var re = _.omit( obj, "works2", "works5" );
_.omit = function(obj, iteratee, context) {
// 第2引数が関数なら
if (_.isFunction(iteratee)) {
// 関数の返す真偽値の反対を返す関数を返す。
iteratee = _.negate(iteratee);
} else {
// 第2引数以降をまとめた配列。
var keys = _.map(flatten(arguments, false, false, 1), String);
// 第2引数以降をまとめた配列に入力されたkey値が含まれていたら、false を返す関数。
iteratee = function(value, key) {
return !_.contains(keys, key);
};
}
// 第1引数と条件によって設定された iteratee が _.pick() に渡される。
return _.pick(obj, iteratee, context);
};
var re = _.noop;
// _.noop()
console.log( re );
// undefined
console.log( JSON.stringify( re ) );
_.noop = function(){};
var Psyclopedia = _.noConflict();
// re = [ ];
var re = Psyclopedia.functions( _ );
// re2 = [ "after", "all", "allKeys", "any", "assign", "before", "bind", "bindAll", "chain", "clone", 他 121 個... ];
var re2 = Psyclopedia.functions( Psyclopedia );
// 内部で宣言されている。
var previousUnderscore = root._;
_.noConflict = function() {
root._ = previousUnderscore;
// this は Underscore自身。
return this;
};
var obj = {
start : 5,
end : 12
};
var func = function( val, key ){
return val + 5;
}
// re = { start: 10, end: 17 };
var re = _.mapObject( obj, func );
_.mapObject = function(obj, iteratee, context) {
// 第3引数が入力されていない、第2引数が関数ならそのまま。
iteratee = cb(iteratee, context);
// 第1引数のkey値を抽出した配列を作る。
var keys = _.keys(obj),
// 配列の長さを抽出。
length = keys.length,
results = {},
currentKey;
// 第1引数のObjectの各値に第2引数の関数を適用するforループ。
for (var index = 0; index < length; index++) {
currentKey = keys[index];
// 第2引数の関数に第1引数の各値とそのkey値と第1引数自身を渡す。
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
}
// 関数を適用した第1引数を返す。
return results;
};
var obj = {
music : "Psyclopedia",
author : "PSY・S [saiz]"
}
// re = true;
var re = _.isObject( obj );
var func = function(){
this.works = "Psyclopedia";
this.author = "PSY・S [saiz]";
this.music = "ファジイな痛み";
this.music3 = "遠い空";
this.music4 = "Parashute Limit";
this.music5 = "Angel Night 天使のいる場所";
};
// re2 = true;
var re2 = _.isObject( new func() );
// 引数が typeof 判定で "function" か "object" で 引数が null じゃない時、true を返す。
_.isObject = function(obj) {
var type = typeof obj;
return type === "function" || type === "object" && !!obj;
};
var obj = {
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
};
// re = [ "title", "year", "author" ];
var re = _.keys( obj );
_.keys = function(obj) {
// 引数が Object じゃない時。
if (!_.isObject(obj)) return [];
// Underscore 内部で nativeKeys = Object.keys; が宣言されているので、あれば適用する。
if (nativeKeys) return nativeKeys(obj);
var keys = [];
// Object の key値 を抽出して obj が key値 を持っていたら、 keys 配列に入れるforループ。
for (var key in obj) if (_.has(obj, key)) keys.push(key);
// IE9用と思われる部分。未検証。
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
// 結果の配列を返す。
return keys;
};
var arr = [
{ works : "悠久の社", author : "kokia" },
{ works : "Currents", author : "kokia,上野洋子" },
{ works : "愛の輪郭", author : "kokia" },
{ works : "The Voice", author : "kokia" },
{ works : "I believe 海の底から", author : "kokia" },
{ works : "調和", author : "kokia" }
];
// re = [ "悠久の社", "Currents", "愛の輪郭", "The Voice", "I believe 海の底から", "調和" ];
var re = _.map( arr, _.iteratee("works"));
// re2 = [ [{"works":"悠久の社","author":"kokia"},{"works":"Currents","author":"kokia,上野洋子"},{"works":"愛の輪郭","author":"kokia"},{"works":"The Voice","author":"kokia"},
{"works":"I believe 海の底から","author":"kokia"},{"works":"調和","author":"kokia"}], [] ];
var re2 = _.partition( arr, _.iteratee("works"));
_.iteratee = function(value, context) {
// cb関数は第1引数「value」が関数でない場合は、_.matcher(value); か _.property(value); に代入される。
return cb(value, context, Infinity);
};
// re = true;
var re = _.isUndefined( undefined );
// re2 = false;
var re2 = _.isUndefined( null );
_.isUndefined = function(obj) {
// 引数が void 0 だった時に true を返す。
return obj === void 0;
};
var txt = "ファジイな痛み";
var num = 2015;
// re = true;
var re = _.isString( txt );
// re = false;
var re = _.isString( num );
// var toString = ObjProto.toString;
// _[isString] = function( obj ){ return toString.call(obj) === "[object String]"; }
_.each(["Arguments", "Function", "String", "Number", "Date", "RegExp", "Error"], function(name) {
_["is" + name] = function(obj) {
return toString.call(obj) === "[object " + name + "]";
};
});
// re = true;
var re = _.isRegExp( /Psyclopedia/ );
// re2 = false;
var re2 = _.isRegExp( "Psyclopedia" );
// var toString = ObjProto.toString;
// _[isRegExp] = function( obj ){ return toString.call(obj) === "[object RegExp]"; }
_.each(["Arguments", "Function", "String", "Number", "Date", "RegExp", "Error"], function(name) {
_["is" + name] = function(obj) {
return toString.call(obj) === "[object " + name + "]";
};
});
var txt = "ファジイな痛み";
var num = 2015;
// re = false;
var re = _.isNumber( txt );
// re2 = true;
var re2 = _.isNumber( num );
// var toString = ObjProto.toString;
// _[isNumber] = function( obj ){ return toString.call(obj) === "[object Number]"; }
_.each(["Arguments", "Function", "String", "Number", "Date", "RegExp", "Error"], function(name) {
_["is" + name] = function(obj) {
return toString.call(obj) === "[object " + name + "]";
};
});
// re = true;
var re = _.isNaN( NaN );
// re2 = true;
var re2 = isNaN( undefined );
// re3 = false;
var re3 = _.isNaN( undefined );
_.isNaN = function(obj) {
// 引数が数字で、「obj !== +obj」が ture の時、ture を返す。
return _.isNumber(obj) && obj !== +obj;
};
var obj = {
music : "弦楽四重奏によるドラゴンクエスト",
author : "すぎやまこういち",
game : {}
}
var obj2 = {
music : "弦楽四重奏によるドラゴンクエスト",
}
var obj3 = {
music : "金管五重奏によるドラゴンクエスト",
author : "すぎやまこういち"
}
// re = true;
var re = _.isMatch( obj, obj2 );
// re2 = false;
var re2 = _.isMatch( obj, obj3 );
_.isMatch = function(object, attrs) {
// 第2引数の key 値の配列を作成。
var keys = _.keys(attrs), length = keys.length;
// 第1引数 == null だったら。
if (object == null) return !length;
// 第1引数 を Objectラッパーで包む。
var obj = Object(object);
// 第2引数のkey値とその値が第1引数に含まれているかを調べるforループ。
for (var i = 0; i < length; i++) {
var key = keys[i];
// 第2引数と第1引数の key値 とその値が違うか、Objectラッパーで包まれた第1引数に key値 が含まれなかったら false を返す。
if (attrs[key] !== obj[key] || !(key in obj)) return false;
}
return true;
};
// re = true;
var re = _.isNull(null);
// re = false;
var re2 = _.isNull(undefined);
_.isNull = function(obj) {
// 引数が null だった時に true を返す。
return obj === null;
};
var func = function(){
this.works = "Psyclopedia";
this.author = "PSY・S [saiz]";
this.music = "ファジイな痛み";
this.music3 = "遠い空";
this.music4 = "Parashute Limit";
this.music5 = "Angel Night 天使のいる場所";
console.log( this.works + " : " + this.author );
};
// コンソールに表示され、re = false;
var re = _.isFunction( new func() );
// コンソールに表示されない。re2 = true;
var re2 = _.isFunction( func );
// var toString = ObjProto.toString;
// _[isFunction] = function( obj ){ return toString.call(obj) === "[object Function]"; }
_.each(["Arguments", "Function", "String", "Number", "Date", "RegExp", "Error"], function(name) {
_["is" + name] = function(obj) {
return toString.call(obj) === "[object " + name + "]";
};
});
// if (typeof /./ != "function" && typeof Int8Array != "object") が true なので if 文が実行され _.isFunction() が上書きされる。
if (typeof /./ != "function" && typeof Int8Array != "object") {
_.isFunction = function(obj) {
// typeof obj == "function" が true なら true が返される。
return typeof obj == "function" || false;
};
}
var num = 2015;
var num2 = Infinity;
var num3 = NaN;
// re = true;
var re = _.isFinite( num );
// re2 = false;
var re2 = _.isFinite( num2 );
// re3 = false;
var re3 = _.isFinite( num3 );
// re4 = false;
var re4 = isFinite(num2);
// re5 = false;
var re5 = isFinite(num3);
_.isFinite = function(obj) {
// 引数を isFinite() 関数(有限数を判断する関数。)に代入。また引数を浮動小数点の数に直してisNaN()関数に代入。両方とも true の時に true を返す。;
return isFinite(obj) && !isNaN(parseFloat(obj));
};
var obj = {
music : "弦楽四重奏によるドラゴンクエスト",
author : "すぎやまこういち",
game : {}
}
var obj2 = {
music : "弦楽四重奏によるドラゴンクエスト",
author : "すぎやまこういち",
game : {}
}
// re = true;
var re = _.isEqual( obj, obj2 );
_.isEqual = function(a, b) {
// 引数を内部関数eq()に代入し結果を返す。
return eq(a, b);
};
var eq = function(a, b, aStack, bStack) {
if (a === b) return a !== 0 || 1 / a === 1 / b;
// 「null = undefined」用
if (a == null || b == null) return a === b;
// a,b が _の instance だった時。
if (a instanceof _) a = a._wrapped;
if (b instanceof _) b = b._wrapped;
// 第1引数の型が文字列になる。
// Array だったら [object Array]、Object だったら [object Object]、arguments は [object Arguments]、function は [object Function]、
// 文字列だったら [object String]、数字は [object Number]。
var className = toString.call(a);
// 第1引数と第2引数の型が違ったら、false を返す。
if (className !== toString.call(b)) return false;
// 型の種類によって対応を分ける。
switch (className) {
// 型が 正規表現 だったら。
case "[object RegExp]":
// RegExps are coerced to strings for comparison (Note: "" + /a/i === "/a/i")
// 型が 文字列 だったら。
case "[object String]":
return "" + a === "" + b;
// 型が 数字 だったら。
case "[object Number]":
if (+a !== +a) return +b !== +b;
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
// 型が Date Object だったら。
case "[object Date]":
// 型が 真偽値 だったら。
case "[object Boolean]":
return +a === +b;
}
var areArrays = className === "[object Array]";
// 型が 配列 じゃなかったら。
if (!areArrays) {
// 第1引数もしくは第2引数の型が object でない場合。
if (typeof a != "object" || typeof b != "object") return false;
var aCtor = a.constructor, bCtor = b.constructor;
// 第1引数と第2引数の Constructor が違うなど下記条件が全部 true なら return false を返す。
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
_.isFunction(bCtor) && bCtor instanceof bCtor)
&& ("constructor" in a && "constructor" in b)) {
return false;
}
}
// //型が 配列 じゃなかったら。
// 再帰処理された時は、各値の出所の配列(Object)などが入っている。
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length;
// 配列、Object の値がまた 配列 か Object の時、while 文が実行される。
while (length--) {
if (aStack[length] === a) return bStack[length] === b;
}
// 配列などの各値を調べる時に元の配列などを入れておく。
aStack.push(a);
bStack.push(b);
// 型が 配列 だったら。
if (areArrays) {
// 第1引数と第2引数のそれぞれの配列の長さが違ったら false を返す。
length = a.length;
if (length !== b.length) return false;
// 配列の各値を再度 eq() に代入。false が返された時、false を返す。
while (length--) {
if (!eq(a[length], b[length], aStack, bStack)) return false;
}
// 型が Object だったら。
} else {
// 第1引数「Object」のkey値の配列を作成。
var keys = _.keys(a), key;
length = keys.length;
// 第1引数と第2引数のkey値の配列の長さが違ったら false を返す。
if (_.keys(b).length !== length) return false;
// 第1引数「Object」の各key値とその値を比べる while ループ。
while (length--) {
key = keys[length];
// 第1引数の key値を第2引数が持っていて、 eq(a[key], b[key], aStack, bStack) の結果が true ならこの if は実行されない。
if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
}
}
// Remove the first object from the stack of traversed objects.
aStack.pop();
bStack.pop();
// 途中で return false; されなかったら true を返す。
return true;
};
var obj = {
music : "弦楽四重奏によるドラゴンクエスト",
author : "すぎやまこういち"
};
var obj2 = {};
// re = false;
var re = _.isEmpty( obj );
// re2 = true;
var re2 = _.isEmpty( obj2 );
var arr = [ 0, 1, 2, ];
var arr2 = [];
// re = false;
var re = _.isEmpty( arr );
// re2 = true;
var re2 = _.isEmpty( arr2 );
_.isEmpty = function(obj) {
// 引数が null なら
if (obj == null) return true;
// 引数が arguments か 配列 か 文字列 の時は length === 0 の真偽値を返す。
if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
// 引数がObjectなら key値の配列を作成して長さの真偽値を返す。
return _.keys(obj).length === 0;
};
var doc = document;
var elem = doc.querySelectorAll("body");
var obj = {
music : "Psyclopedia",
author : "PSY・S [saiz]"
}
// re = true;
var re = _.isElement( elem[0] );
// re = false;
var re2 = _.isElement( obj );
_.isElement = function(obj) {
// 引数が null 以外で、引数が nodeType === 1 の時、 true を返す。
return !!(obj && obj.nodeType === 1);
};
var obj = {
works : "Psyclopedia",
author : "PSY・S [saiz]",
music : "ファジイな痛み",
music2 : "遠い空",
music3 : "Parashute Limit",
music4 : "Angel Night 天使のいる場所"
}
var func = function(){
return _.isArguments( arguments );
};
// re = true;
var re = func( obj );
// var toString = ObjProto.toString;
// _[isArguments] = function( obj ){ return toString.call(obj) === "[object Arguments]"; }
_.each(["Arguments", "Function", "String", "Number", "Date", "RegExp", "Error"], function(name) {
_["is" + name] = function(obj) {
return toString.call(obj) === "[object " + name + "]";
};
});
// IE9未満のブラウザ用と思われる(未検証)。if (!_.isArguments(arguments)) が基本 false で実行されないので。
if (!_.isArguments(arguments)) {
_.isArguments = function(obj) {
return _.has(obj, "callee");
};
}
// re = true;
var re = _.isDate(new Date());
// re2 = false;
var re2 = _.isDate( 2015 );
// var toString = ObjProto.toString;
// _[isDate] = function( obj ){ return toString.call(obj) === "[object Date]"; }
_.each(["Arguments", "Function", "String", "Number", "Date", "RegExp", "Error"], function(name) {
_["is" + name] = function(obj) {
return toString.call(obj) === "[object " + name + "]";
};
});
// re = true;
var re = _.isBoolean( true );
// re2 = true;
var re2 = _.isBoolean( false );
// re3 = false;
var re3 = _.isBoolean( null );
// re4 = false;
var re4 = _.isBoolean( undefined );
_.isBoolean = function(obj) {
// 引数が true か false か 型の文字列が [object Boolean] だった時に返す。
return obj === true || obj === false || toString.call(obj) === "[object Boolean]";
};
var arr = [ 0, 1, 2 ];
// re = true;
var re = _.isArray( arr );
var arr = [ 0, 1, 2 ];
var func = function(){ return _.isArray(arguments) };
// re2 = false;
var re2 = func( arr );
// 内部で var nativeIsArray = Array.isArray; が宣言されている。
// 内部で var toString = ObjProto.toString; が宣言されている。
// nativeIsArray が機能する場合は、nativeIsArrayを使って判定。使えない場合は toString で文字列が [object Array] の時、true を返す。
_.isArray = nativeIsArray || function(obj) {
return toString.call(obj) === "[object Array]";
};
var obj = {
title : "飛行夢",
year : 1989,
author : "Zabadak"
};
// { 飛行夢: "title", 1989: "year", Zabadak: "author" };
var re = _.invert( obj );
_.invert = function(obj) {
var result = {};
// 引数のkey値を抽出した配列を作る。
var keys = _.keys(obj);
// 引数のkey値とその値を入れ替えたObjectを作るforループ。
for (var i = 0, length = keys.length; i < length; i++) {
result[obj[keys[i]]] = keys[i];
}
return result;
};
// [ "after", "all", "allKeys", "any", "assign", "before", "bind", "bindAll", "chain", "clone", ... ];
var re = _.functions( _ );
_.functions = _.methods = function(obj) {
// 結果出力用の配列を作る。
var names = [];
// 引数「obj」のkey値の値を関数かどうか判別するforループ。;
for (var key in obj) {
// そのkey値の値が関数だった時に、結果用の配列に入れる。
if (_.isFunction(obj[key])) names.push(key);
}
// 結果用の配列をソートする。
return names.sort();
};
function Zabadak( name ) {
this.vocal = "上野洋子";
this.guitar = "吉良知彦";
this.works = name;
};
Zabadak.prototype.oldmember = "松田克志";
var func = new Zabadak( "桜" );
var obj = {
title : "遠い音楽",
year : 1990,
author : "Zabadak"
};
// { title: "遠い音楽", year: 1990, author: "Zabadak", vocal: "上野洋子", guitar: "吉良知彦", works: "桜" }
var re = _.extendOwn( obj, func );
// _.keys() 関数をcreateAssigner()関数に渡す。createAssignerからは部分適用した関数が返ってくる。
_.extendOwn = _.assign = createAssigner(_.keys);
function Zabadak( name ) {
this.vocal = "上野洋子";
this.guitar = "吉良知彦";
this.works = name;
};
Zabadak.prototype.oldmember = "松田克志";
var func = new Zabadak( "桜" );
var obj = {
title : "遠い音楽",
year : 1990,
author : "Zabadak"
};
// { title: "遠い音楽", year: 1990, author: "Zabadak", vocal: "上野洋子", guitar: "吉良知彦", works: "桜", oldmember: "松田克志" };
var re = _.extend( obj, func );
// _.allKeys() 関数をcreateAssigner()関数に渡す。createAssignerからは部分適用した関数が返ってくる。
_.extend = createAssigner(_.allKeys);
var obj = {
music : "Reincarnation",
music2 : "花かんむり",
author : "Goddes in the morning"
}
var obj2 = {
music : "窓枠の花",
music2 : "flower crown",
music3 : "逆さまの虹",
music4 : "Little Wing",
music5 : "Wanna be an angel",
author : "新居昭乃"
}
// re = { music: "Reincarnation", music2: "花かんむり", author: "Goddes in the morning" };
var re = _.create( obj2, obj );
// re2 = [ "music", "music2", "author", "music3", "music4", "music5" ];
var re2 = _.allKeys( re );
_.create = function(prototype, props) {
// 第1引数をプロトタイプとする新規Objectを作成する。
var result = baseCreate(prototype);
// 第2引数のプロパティーを result にコピーする。
if (props) _.extendOwn(result, props);
// CMS tool エラーのためリターンの綴り変えています。
retu(r)n result;
};
var str = "Kokia & 上野洋子";
// "Kokia &amp; 上野洋子"
console.log(_.escape(str) );
_.escape = createEscaper(escapeMap);
var escapeMap = {
"&" : "&amp;",
"<" : "&lt;",
">" : "&gt;",
'"' : "&quot;",
"'" : "x27;",
"`" : "x60;"
};
var createEscaper = function(map) {
var escaper = function(match) {
// return escapeMap[match]
return map[match];
};
var source = "(?:" + _.keys(map).join("|") + ")";
// testRegexp = /(?:&|<|>|"|'|`)/;
var testRegexp = RegExp(source);
// replaceRegexp = /(?:&|<|>|"|'|`)/g;
var replaceRegexp = RegExp(source, "g");
// _.escape() の引数はこの返される関数の引数。
return function(string) {
string = string == null ? "" : "" + string;
// testRegexp.test(string); が false なら _.escape() の引数は何もされずに返る。
// testRegexp.test(string); が true なら マッチした文字が escaper() に渡されマッチした文字が置き換えられる。
// CMS tool のエラーのためリプレイスの表記少し変えています。
return testRegexp.test(string) ? string.r(e)place(replaceRegexp, escaper) : string;
};
};
var arr = [
{ works : "Psyclopedia", author : "PSY・S [saiz]" },
{ works : "ファジイな痛み", author : "PSY・S [saiz]" },
{ works : "遠い空", author : "PSY・S [saiz]" },
{ works : "Parashute Limit", author : "PSY・S [saiz]" },
{ works : "Angel Night 天使のいる場所", author : "PSY・S [saiz]" }
];
// re = Angel Night 天使のいる場所 : PSY・S [saiz]
var re = _.chain( arr )
.sortBy("works")
.map( function( artist ) { return artist.works + " : " + artist.author; } )
.first()
.value();
var arr = [
{ works : "Psyclopedia", author : "PSY・S [saiz]" }
];
// re は Undescore のインスタンスで re._wrapped に _() での引数を持っている。
var re = _.chain( arr );
// [{"works":"Psyclopedia","author":"PSY・S [saiz]"}];
console.log( re._wrapped );
// true
console.log( re._chain );
_.chain = function(obj) {
// _ のインスタンス( instance )を作成。_chain を true にして instance を返す。
var instance = _(obj);
instance._chain = true;
return instance;
};
// Undersocre JS内部で以下が宣言されている。
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
function Zabadak( name ) {
this.vocal = "上野洋子";
this.guitar = "吉良知彦";
this.works = name;
};
Zabadak.prototype.oldmember = "松田克志";
var func = new Zabadak( "桜" );
var obj = {
title : "遠い音楽",
year : 1990,
author : "Zabadak",
works : undefined
};
// { title: "遠い音楽", year: 1990, author: "Zabadak", works: "桜", vocal: "上野洋子", guitar: "吉良知彦", oldmember: "松田克志" };
var re = _.defaults( obj, func );
// _.allKeys() 関数をcreateAssigner() 関数に渡す。createAssignerからは部分適用した関数が返ってくる。
_.defaults = createAssigner(_.allKeys, true);
// _.defaults = createAssigner(_.allKeys, true);
var createAssigner = function(keysFunc, undefinedOnly) {
// createAssignerから返される部分適用した関数。
return function(obj) {
// 返される関数の引数の長さ。
var length = arguments.length;
// 引数の長さが2未満か引数が null だった場合。
if (length < 2 || obj == null) return obj;
// 返される関数の引数が2つ以上の時の処理。
for (var index = 1; index < length; index++) {
// 第2引数から
var source = arguments[index],
// keysFunc は _.keys() か _.allKeys() どちらか。
// 第2引数以降の引数のkey値の配列作成。
keys = keysFunc(source),
l = keys.length;
// 第2引数「Object」のkey値とその値を第1引数「Object」にコピーするループ。
for (var i = 0; i < l; i++) {
var key = keys[i];
// _.defaults = createAssigner(_.allKeys, true);、_.extend(),_.extendOwn() はこのif文は必ず実行される。
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
}
}
// コピーされた第1引数を返す。
return obj;
};
};
var obj = {
works : "The Voice",
author : "kokia"
};
// re = true;
var re = obj === _.constant( obj )();
var arr = [
{ works : "悠久の社", author : "kokia" },
{ works : "Currents", author : "kokia,上野洋子" },
{ works : "愛の輪郭", author : "kokia" },
{ works : "I believe 海の底から", author : "kokia" },
{ works : "調和", author : "kokia" }
];
// re2 = true;
var re2 = arr === _.constant( arr )();
_.constant = function(value) {
// 受け取った引数を部分適用してただ引数を返す関数(返される関数は引数は取らない。)を返す。
return function() {
return value;
};
};
var obj = {
music : "弦楽四重奏によるドラゴンクエスト",
author : "すぎやまこういち"
}
// re = { "music":"弦楽四重奏によるドラゴンクエスト","author":"すぎやまこういち" };
var re = _.clone( obj );
var obj = {
music : "金管五重奏によるドラゴンクエスト",
author : "すぎやまこういち"
}
var obj2 = {
music : "弦楽四重奏によるドラゴンクエスト",
author : "すぎやまこういち"
}
var func = function(){
return _.clone( arguments );
}
// re = { "0" : {"music":"金管五重奏によるドラゴンクエスト","author":"すぎやまこういち"}, "1" : {"music":"弦楽四重奏によるドラゴンクエスト","author":"すぎやまこういち"} };
var re = func( obj, obj2 );
_.clone = function(obj) {
// 引数が「Object」じゃなかったら。
if (!_.isObject(obj)) return obj;
// 引数が配列だったら obj.slice、配列以外( arguments含む )だったら空のObjectにコピーする(プロトタイプを含む)。
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
function DQ( name ){
this.music = "弦楽四重奏によるドラゴンクエスト";
this.author = name;
}
DQ.prototype.famicon = true;
// re = [ "music", "author", "famicon" ]
var re = _.allKeys( new DQ("すぎやまこういち") );
_.allKeys = function(obj) {
// 引数が Object じゃない時。
if (!_.isObject(obj)) return [];
var keys = [];
// Object のkey値を抽出してkeys配列に入れるforループ。
for (var key in obj) keys.push(key);
// IE9用と思われる部分。未検証。
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
// 結果の配列を返す。
return keys;
};
var subtract = function( a, b ){
return a - b;
}
var sub5 = _.partial( subtract, 5 );
var subForm20 = _.partial( subtract, _, 20 );
// re = -15;
var re = sub5( 20 );
// re2 = -15;
var re2 = subForm20( 5 );
_.partial = function(func) {
// 第2引数以降の引数。
var boundArgs = slice.call(arguments, 1);
// _.partial()に返される関数。
var bound = function() {
var position = 0, length = boundArgs.length;
var args = Array(length);
// _.partial()の引数をargsに格納するforループ。boundArgs[i] の値で「_」だった時は arguments[position++];
for (var i = 0; i < length; i++) {
// arguments は bound()の引数。
args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
}
// bound()の引数をargsに追加するwhileループ。
while (position < arguments.length) args.push(arguments[position++]);
// executeBound()に代入。
return executeBound(func, bound, this, this, args);
};
// bound() 定義終了。
return bound;
};
var arr001 = ["moe", "larry", "curly" ];
var arr002 = [30, 40, 50, 60];
var arr003 = [true, false, false, true, false];
// re = [ ["moe",30,true], ["larry",40,false], ["curly",50,false], [null,60,true], [null,null,false] ];
var re = _.zip( arr001, arr002, arr003 );
_.zip = function() {
// 引数を _.unzip() に渡す。
return _.unzip(arguments);
};
var i = 0;
function logged( txt ){
var text = txt ? txt : "test";
text = text + " " + i;
i++;
return text;
}
var re = _.wrap( logged, function(func) {
var text = func("logged関数") + " is wrapped ";
console.log( text );
});
// logged関数 0 is wrapped
re();
// logged関数 1 is wrapped
re();
_.wrap = function(func, wrapper) {
// 部分適用関数_.partial() に渡す。
return _.partial(wrapper, func);
};
var arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = [ 2, 3, 4, 5, 6, 7, 8, 9 ];
var re = _.without( arr, 0, 1, 10 );
var arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = [ 0, 1, 3, 4, 6, 7, 8, 9, 10 ];
var re = _.without( arr, 2, 5, 50, 45, 30, -5 );
_.without = function(array) {
// 第1引数「配列」と第2引数以降が配列となって渡される。
// 上の使用例1だと[ [ 0,1,2,3,4,5,6,7,8,9,10 ], [ 0,1,10 ] ]
return _.difference(array, slice.call(arguments, 1));
};
var arr001 = ["moe", "larry", "curly" ];
var arr002 = [30, 40, 50, 60];
var arr003 = [true, false, false, true, false];
var re = _.zip( arr001, arr002, arr003 );
// un_re = [ ["moe","larry","curly",null,null], [30,40,50,60,null], [true,false,false,true,false] ];
var un_re = _.unzip( re );
_.unzip = function(array) {
// それぞれの引数(配列)の中で1番大きい length の値が length になる。
var length = array && _.max(array, "length").length || 0;
// 結果用の配列作成。
var result = Array(length);
// _.pluck() により各配列のそれぞれの index の値を抽出した配列をresult配列に格納する。
for (var index = 0; index < length; index++) {
result[index] = _.pluck(array, index);
}
return result;
};
var arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 4, 5, 7, 9, false, undefined, undefined ];
// re = [ 0,1,2,3,4,5,6,7,8,9,10,false,undefined ];
var re = _.uniq( arr );
var arr = [ 0, 1, 2, 10, 2 ];
// re = [ 0,1,2,10 ];
var re = _.uniq( arr );
_.uniq = _.unique = function(array, isSorted, iteratee, context) {
// 第1引数が null の時は空の配列が返る。
if (array == null) return [];
// _.isBoolean() は「true」「false」の時、trueを返すので 第2引数が「undefined」「null」の時などの処理。
if (!_.isBoolean(isSorted)) {
context = iteratee;
iteratee = isSorted;
isSorted = false;
}
// iteratee が空じゃない時。
if (iteratee != null) iteratee = cb(iteratee, context);
var result = [];
var seen = [];
// 各値を処理するforループ。
for (var i = 0, length = array.length; i < length; i++) {
var value = array[i],
// iteratee がある時は iteratee で第1引数「配列」の値を処理した結果。iteratee がない場合は値そのまま。
computed = iteratee ? iteratee(value, i, array) : value;
if (isSorted) {
// isSorted = true の時の処理。
// 前の値と違う時
if (!i || seen !== computed) result.push(value);
seen = computed;
} else if (iteratee) {
// iteratee = true の時の処理。
// seen配列に値がない時。
if (!_.contains(seen, computed)) {
seen.push(computed);
result.push(value);
}
// 引数が配列のみで、値が result 配列にない時。
} else if (!_.contains(result, value)) {
result.push(value);
}
}
// 重複していない値が入る配列が返される。
return result;
};
var arr = [ 1, 2, 3 ];
var arr01 = [ 101, 2, 1, 10 ];
var arr02 = [ 2, 1 ];
// re = [ 1, 2, 3, 101, 10 ];
var re = _.union( arr, arr01, arr02 );
var arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 4, 5, 7, 9, false, undefined, undefined ];
var arr01 = [ 101, 2, 1, 10 ];
var arr02 = [ 2, 1 ];
var arr03 = [ false, 1000 ];
// re = [0,1,2,3,4,5,6,7,8,9,10,false,null,101,1000];
var re = _.union( arr, arr01, arr02, arr03 );
_.union = function() {
// 内部関数 flatten() に渡される。arguments は1番浅い配列だけ解消され、一つの配列としてまとめられる。
// _.uniq() で重複した値は消され、重複のない配列となって返される。
return _.uniq(flatten(arguments, true, true));
};
function logged( txt ){
var text = _.now();
console.log( "re now : " + txt + " : " + text );
}
var re = _.throttle( logged, 5000 );
// 即時発動。re now : 0 : 1430734386522
re("0");
re("1");
re("2");
re("3");
re("4");
// re("1") 〜 re("4") までは発動しない。第2引数の時間後 re("5") 発動。 re now : 5 : 1430734391523
re("5");
_.throttle = function(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
// 第3引数が指定されていなかったら
if (!options) options = {};
// _.throttle設定後の最初の関数発動時のsetTimeout関数で呼ばれる関数。
var later = function() {
// later()発動後は 0 が再度設定される。
previous = options.leading === false ? 0 : _.now();
timeout = null;
// context を this にした func( args ) が設定される。
result = func.apply(context, args);
// timeout = null;
if (!timeout) context = args = null;
};
// _.throttle() 設定時に返される関数。使用例の re("1") の引数はこの関数の引数。
return function() {
var now = _.now();
// ここは無視。第3引数が設定されている時なので。
if (!previous && options.leading === false) previous = now;
// 残り時間が設定される。(関数が発動される度に。)_.throttle() 設定後の最初の関数発動時は previous = 0;
var remaining = wait - (now - previous);
// _.throttle() を設定した関数がメソッドでないのであれば this = グローバルオブジェクト。
context = this;
// 返される関数の引数。
args = arguments;
// 残り時間が 0 以下か wait 時間を上まっていたらなのだが、
// _.throttle設定後の最初の関数発動時、remaining の数が 0 以下なの1回目はここを実行する。
if (remaining <= 0 || remaining > wait) {
// 最初は timeout = null; なので
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
// context を this に設定した func( args ) 関数。
result = func.apply(context, args);
// 最初は timeout = null; なので
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
// _.throttle設定後の2回目以降関数発動時に setTimeout が呼ばれる。
timeout = setTimeout(later, remaining);
}
// _.throttle設定後の関数で発動する関数。
// wait時間の間のキャンセルされる関数は undefined が返される。
return result;
};
};
// re = [ 0, 1, 2, 3, 4 ];
var re = _.range( 5 );
// re2 = [ 4, 5, 6, 7, 8, 9 ];
var re2 = _.range( 4,10 );
// re3 = [ 0, 5, 10, 15, 20, 25 ];
var re3 = _.range( 0,30, 5 );
// re4 = [ 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 ];
var re4 = _.range( 0,-10, -1 );
// re5 = [ ];
var re5 = _.range( 0 );
_.range = function(start, stop, step) {
// 引数が1以下なら
if (arguments.length <= 1) {
// start が falseなら stop = 0;
stop = start || 0;
start = 0;
}
// step が falseなら step = 1;
step = step || 1;
// Math.max() は引数の中で最大の値をとる。
var length = Math.max(Math.ceil((stop - start) / step), 0);
var range = Array(length);
// step 毎の値を length 分格納するforループ。
for (var idx = 0; idx < length; idx++, start += step) {
range[idx] = start;
}
return range;
};
function logged( txt ){
var text = _.now();
console.log( "re now : " + txt + " : " + text );
}
var re = _.once(logged);
var re2 =_.once(logged);
re("01");
re("02");
re2("re2 : 01");
re("03");
re("04");
re2("re2 : 02");
re("05");
re("06");
re2("re2 : 03");
// re("01");とre2("re2 : 01");しか実行されない。
// 指定回数未満しか実行しない_.before()を_.partial()に渡す。
_.once = _.partial(_.before, 2);
var arr001 = ["moe", "larry", "curly" ];
var arr002 = [30, 40, 50];
// re = { "moe":30, "larry":40," curly":50 }
var re = _.object( arr001, arr002 );
var arr = [ [ "moe" , 30 ], [ "larry" , 40 ], [ "curly" , 50] ];
// re = {"moe":30,"larry":40,"curly":50}
var re = _.object( arr );
_.object = function(list, values) {
var result = {};
// result(Object)に key : val をそれぞれ設定するforループ。
for (var i = 0, length = list && list.length; i < length; i++) {
// 第2引数が ture なら
if (values) {
result[list[i]] = values[i];
} else {
// 第1引数のみなら
result[list[i][0]] = list[i][1];
}
}
return result;
};
var re = _.now();
// 1430725437262
console.log( re );
// Date.now が true なら Date.now を返す。
_.now = Date.now || function() {
return new Date().getTime();
};
var obj = [
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
}
];
var pre = { author : "Michiru Yamane" };
var func = function( key ){
return _.where( obj, key );
}
var memo = _.memoize( func );
// re =[ {"title":"悪魔城ドラキュラX 月下の夜想曲","year":1994,"author":"Michiru Yamane"} ];
var re = func( pre );
// re2 =[ {"title":"悪魔城ドラキュラX 月下の夜想曲","year":1994,"author":"Michiru Yamane"} ];
var re2 = memo( pre );
obj.shift();
// re3 = [];
var re3 = func( pre );
// re4 =[ {"title":"悪魔城ドラキュラX 月下の夜想曲","year":1994,"author":"Michiru Yamane"} ];
var re4 = memo( pre );
_.memoize = function(func, hasher) {
// 最後に返されるmemoize関数定義。
var memoize = function(key) {
var cache = memoize.cache;
// hasher が「undefined」なら address = key;
// this = window;
var address = "" + (hasher ? hasher.apply(this, arguments) : key);
// cache Object に address のプロパティがなかったら値の結果をキャッシュする。
if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
// 結果を返す。
return cache[address];
};
// 空Object設定。
memoize.cache = {};
// _.memoize() は部分適用された memoize関数が返される。
return memoize;
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var arr2 = [10, 20, 30, NaN, 40, 50];
var num = 5;
var num2 = NaN;
var num3 = 13;
// re = 4
var re = _.lastIndexOf( arr, num );
// re2 = 3
var re2 = _.lastIndexOf( arr2, num2, 3 );
// re3 = -1
var re3 = _.lastIndexOf( arr, num3 );
_.lastIndexOf = function(array, item, from) {
// array が true なら idx = array.length;
var idx = array ? array.length : 0;
// 第3引数が数字なら
if (typeof from == "number") {
// fromが0未満なら idx = idx + from + 1;
// fromが1以上なら idxと(from + 1)の数が少ない方が idx に代入される。
idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
}
// if (item !== item) は item = NaN の時 if 文が実行される。
if (item !== item) {
return _.findLastIndex(slice.call(array, 0, idx), _.isNaN);
}
// 第1引数の後ろから値を調べられ、第2引数の値と同じものがあった場合、そのIndex値が返される。
// 同じ値がなければ「-1」が返される
while (--idx >= 0) if (array[idx] === item) return idx;
return -1;
};
var arr = [ 1, 2, 3 ];
var arr01 = [ 101, 2, 1, 10 ];
var arr02 = [ 2, 1 ];
// re = [ 1, 2 ];
var re = _.intersection( arr, arr01, arr02 );
var arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 4, 5, 7, 9, false, undefined, undefined ];
var arr01 = [ 101, 2, 1, 10 ];
var arr02 = [ 2, 1 ];
var arr03 = [ false, 1000 ];
// re = [ ];
var re = _.intersection( arr, arr01, arr02, arr03 );
_.intersection = function(array) {
if (array == null) return [];
var result = [];
// 引数の長さを抽出。
var argsLength = arguments.length;
// 第1引数「配列」の各値が第2引数以降の引数(配列)に値が含まれているかを確認するforループ。
for (var i = 0, length = array.length; i < length; i++) {
var item = array[i];
// result配列に値があったら、この値の処理をskip。次の値を処理。
if (_.contains(result, item)) continue;
// 第2引数以降の引数(配列)に第1引数の各値がなかったら break。
for (var j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
// 第1引数の値が第2引数以降の配列にそれぞれ同じ値があったら、result配列に入れる。
if (j === argsLength) result.push(item);
}
// forループ終わり。
return result;
};
var arr = [1, [2], [3, [ [4] ] ] ];
// re = [ 1, 2, 3, 4 ];
var re = _.flatten( arr );
var arr = [1, [2], [3, [ [4] ] ] ];
// re2 = [1,2,3,[ [4] ] ];
var re2 = _.flatten( arr, true);
_.flatten = function(array, shallow) {
return flatten(array, shallow, false);
};
// _.flatten() の引数は以下の関数に代入される。
var flatten = function(input, shallow, strict, startIndex) {
var output = [], idx = 0;
// for( var i = 0, length = array.length; i < length; i++ ){
for (var i = startIndex || 0, length = input && input.length; i < length; i++) {
// 配列の各値。
var value = input[i];
// 各値が配列、arguments である場合
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
// 第2引数が「true」指定されている時は再帰処理しない。1回しか配列を解消しない。
if (!shallow) value = flatten(value, shallow, strict);
var j = 0, len = value.length;
output.length += len;
// 各値が配列でない時、 j = 0 < len = 0 なのでこの処理は行われない。
while (j < len) {
output[idx++] = value[j++];
}
} else if (!strict) {
// 各値が結果出力用の配列に入れられる。
output[idx++] = value;
}
}
return output;
};
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
// boundFunc関数のインスタンスじゃない時。
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
// self は sourceFunc.prototypeをプロトタイプとする新規のObjectを返す。
var self = baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
// result が Object の時。
if (_.isObject(result)) return result;
return self;
};
var arr001 = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var arr002 = [ 0, 1, 2, 10 ];
// re = [ 3, 4, 5, 6, 7, 8, 9 ];
var re = _.difference( arr001, arr002 );
_.difference = function(array) {
// 第2引数をまとめた配列 = rest。
// 第2引数以降の引数(配列)が入れ子の場合は一つだけしか解消しない。第2引数以降の引数でObjectがある場合は、そのObjectの値は入らない。
var rest = flatten(arguments, true, true, 1);
// _.filter() 処理された配列が返る。
return _.filter(array, function(value){
// restに含まれる値がある時は「false」を返す。
return !_.contains(rest, value);
});
};
function logged( txt ){
var text = _.now();
console.log( "re now : " + txt + " : " + text );
}
// re now : test : _.now()関数の数字。
var re = _.delay( logged, 1000, "test");
_.delay = function(func, wait) {
// 第3引数以降の引数。
var args = slice.call(arguments, 2);
// 第2引数が setTimeout() にセットされ返される。
return setTimeout(function(){
return func.apply(null, args);
}, wait);
};
function logged( txt ){
var text = _.now();
console.log( "re now : " + txt + " : " + text );
}
var re = _.debounce( logged, 2000 );
re("0");
re("1");
re("2");
re("3");
re("4");
// re("0") 〜 re("4") までは発動しない。re now : 5 : 1430745777135
re("5");
function logged( txt ){
var text = _.now();
console.log( "re now : " + txt + " : " + text );
}
var re2 = _.debounce( logged, 5000, true );
re2("re2 : 0");
re2("re2 : 1");
// re("1") 〜 re("2") までは発動しない。re now : re2 : 0 : 1430746092571
re2("re2 : 2");
_.debounce = function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
// setTimeout() で呼ばれる関数。
var later = function() {
var last = _.now() - timestamp;
if (last < wait && last >= 0) {
// 初回関数発動時からの経過時間が wait 以下で 0 以上の時。
timeout = setTimeout(later, wait - last);
} else {
// 初回関数発動時からの経過時間が wait を超えた時。
timeout = null;
if (!immediate) {
// _.debounce() の第3引数が false なら。
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
};
// _.debounce() 設定後に返される関数。
return function() {
// 基本的には this = グローバルオブジェクト。
context = this;
// この関数の引数。
args = arguments;
timestamp = _.now();
var callNow = immediate && !timeout;
// timeout == null なら
if (!timeout) timeout = setTimeout(later, wait);
if (callNow) {
// _.debounce() の第3引数が true なら設定後の初回時の関数は以下を設定。
result = func.apply(context, args);
context = args = null;
}
return result;
};
};
var arr = [ 1, undefined, 2, false, true, 3, "", 4, null, 10, 0, NaN, 5];
// re = [ 1, 2, true, 3, 4, 10, 5 ];
var re = _.compact( arr );
_.compact = function(array) {
// 引数と_.identity(配列の各値をそのまま返す関数)を_.filter() に渡す。
// 配列の各値で「false」になるものは_.filter でブロックされるので配列に入れられない。
return _.filter(array, _.identity);
};
var buttonView = {
label : "underscore",
onClick: function(){ console.log("clicked: " + this.label); },
onHover: function(){ console.log("hovering: " + this.label); }
};
var re = _.bindAll(buttonView, "onClick", "onHover");
// console に「clicked: underscore」が出力される。
re.onClick();
// console に「hovering: underscore」が出力される。
re.onHover();
_.bindAll = function(obj) {
var i, length = arguments.length, key;
// arguments が1以下なら
if (length <= 1) throw new Error( "bindAll must be passed function names" );
// 第1引数「Object」のメソッドに this ( 第1引数自身 )を設定するforループ。
for (i = 1; i < length; i++) {
key = arguments[i];
obj[key] = _.bind(obj[key], obj);
}
// 第1引数「Object」を返す。
return obj;
};
var func = function(greeting){
return greeting + " : " + this.name;
};
var obj = { name : "moe" };
var txt = "hi";
var re = _.bind( func, obj );
// re = "hi : moe";
re( txt );
_.bind = function(func, context) {
// Undescore JS 内で nativeBind = FuncProto.bind が宣言されている。
// nativeBind が宣言されていて第1引数が nativeBind を継承している時,
// func.bind( slice.call(arguments, 1) ); が返される。
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
// 第1引数「func」が関数じゃない時、エラーが投げられる。
if (!_.isFunction(func)) throw new TypeError("Bind must be called on a function");
// 第3引数以降のarguments
var args = slice.call(arguments, 2);
var bound = function() {
// 第1引数の関数が nativeBind を継承していない時はexecuteBound()に代入され返される。
// this = _;
// args.concat( slice.call(arguments) ) は args の配列に arguments の配列を継ぎ足す。
// arguments は配列ではないので Array.concat() だと arguments object のまま継ぎ足される。
// CMS tools のバグのため書き方変えています。
var args2 = func;
var args3 = bound;
var args4 = context;
var args5 = this;
var args6 = args.concat(slice.call(arguments));
return executeBound( args2〜6 );
};
return bound;
};
function logged( txt ){
var text = _.now();
console.log( "re now : " + txt + " : " + text );
}
var re = _.before(5, logged);
re("0");
re("1");
re("2");
re("3");
// re("4"),re("5")は発動しない。
re("4");
re("5");
_.before = function(times, func) {
var memo;
// _.before() 設定時に返される関数。
return function() {
// _.before() の第1引数で設定された数未満までは関数が実行され、それ以降は func = null; になる。
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
};
var Ctor = function(){};
var baseCreate = function(prototype) {
// 引数の型がObjectじゃない時。
if (!_.isObject(prototype)) return {};
// _内で宣言されている。nativeCreate = Object.create;
// 引数をプロトタイプとするObjectを新規作成して返す。
if (nativeCreate) return nativeCreate(prototype);
// nativeCreate = false の時。
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
function logged( txt ){
var text = _.now();
console.log( "re now : " + txt + " : " + text );
}
var re = _.after(4, logged);
var re2 = _.after(2, logged);
re("01");
re("02");
re2("re2 : 01");
re("03");
re("04");
re2("re2 : 02");
re("05");
re("06");
re2("re2 : 03");
// re("04"),re("05"),re("06"),re2("re2 : 02"),re2("re2 : 03") は関数が実行される。
_.after = function(times, func) {
// _.after() 設定時に返される関数。
return function() {
if (--times < 1) {
// _.after() の第1引数の「数 - 1」回、関数が実行されたら、それ以降の関数実行時、第2引数で指定した関数が発動する。
return func.apply(this, arguments);
}
};
};
var cb = function(value, context, argCount) {
// value が null だった場合、次の関数を返す。_.identity = function(value) { return value; };
if (value == null) return _.identity;
// value が関数だった場合、optimizeCb(value, context, argCount);に代入される。
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
// value が関数でなくObjectだった場合、_.matcher(value);に代入される。
if (_.isObject(value)) return _.matcher(value);
// value が関数でなくObjectでない値だった場合、_.property(value);に代入される。
return _.property(value);
};
var optimizeCb = function(func, context, argCount) {
// 第2引数の context が undefined の場合、そのまま func が返る関数。
if (context === void 0) return func;
// メソッド内部で iteratee = optimizeCb(iteratee, context); のような形で呼び出された時、
第3引数の argCount の値によって処理が分かれる。
switch (argCount == null ? 3 : argCount) {
// context を func の this にして arguments の数が条件によって増える。
case 1: return function(value) {
return func.call(context, value);
};
case 2: return function(value, other) {
return func.call(context, value, other);
};
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
context が undefined 以外で argCount が undefined の場合。
return function() {
return func.apply(context, arguments);
};
};
var obj = [
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1992,
author : "Michiru Yamane"
}
];
var pre = { year : 1992 };
// [{"title":"Final Fantasy5 Original SoundTrack","year":1992,"author":"Nobuo Uematu"},
// {"title":"Final Fantasy6 Original SoundTrack","year":1992,"author":"Nobuo Uematu"},
// {"title":"悪魔城ドラキュラX 月下の夜想曲","year":1992,"author":"Michiru Yamane"}]
var re = _.where( obj, pre );
_.where = function(obj, attrs) {
// _.filter()にobjと_.matcher(同じプロパティと値があるかを判別する部分適用した関数)を渡す。
// 条件に該当するものだけの配列を返す。
return _.filter(obj, _.matcher(attrs));
};
var obj = {
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1992,
author : "Michiru Yamane"
};
// [ "悪魔城ドラキュラX 月下の夜想曲", 1992, "Michiru Yamane" ]
var re = _.values( obj );
_.values = function(obj) {
// Object の key 配列を作る。
var keys = _.keys(obj);
// length 抽出。length の長さ分の配列を作る。
var length = keys.length;
var values = Array(length);
// obj の値の全てを配列に入れるforループ。
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]];
}
return values;
};
var obj = {
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
};
// re = [ "悪魔城ドラキュラX 月下の夜想曲", 1994, "Michiru Yamane" ];
var re = _.toArray( obj );
_.toArray = function(obj) {
// obj が false になる時
if (!obj) return [];
// obj が配列なら
if (_.isArray(obj)) return slice.call(obj);
// obj が arguments なら
if (isArrayLike(obj)) return _.map(obj, _.identity);
// obj の値だけを抽出した配列を返す。
return _.values(obj);
};
var arr = [10, 20, 30, 40, 50];
var obj = [{ name : "moe", age : 40 }, { name : "curly", age : 60 }];
var pre = { name : "larry", age : 50 };
// re = 3
var re = _.sortedIndex( arr, 35 );
// re2 = 1
var re2 = _.sortedIndex( obj, pre, "age" );
_.sortedIndex = function(array, obj, iteratee, context) {
// 第3引数「iteratee = undefined」な場合、_.identityが iteratee に渡される。
// 第3引数「iteratee」が関数でなくObjectでない値だった場合、_.property(value)に代入される。
iteratee = cb(iteratee, context, 1);
// 「iteratee」関数に第2引数「obj」を渡した結果。
var value = iteratee(obj);
var low = 0, high = array.length;
// low > high になるまで続く while ループ。
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
var arr = [ 5, 2, 3, 6, 7, 4, 8, , 9, 10 ];
// re = [ 2, 3, 4, 5, 6, 7, 8, 9, 10, undefined ];
var re = _.sortBy( arr );
var obj = [
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
}
];
var func = function( obj ){
return obj.year;
}
// re = [
{"title":"Final Fantasy4 Original SoundTrack","year":1991,"author":"Nobuo Uematu"},
{"title":"Final Fantasy5 Original SoundTrack","year":1992,"author":"Nobuo Uematu"},
{"title":"Final Fantasy6 Original SoundTrack","year":1992,"author":"Nobuo Uematu"},
{"title":"悪魔城ドラキュラX 月下の夜想曲","year":1994,"author":"Michiru Yamane"}
];
var re = _.sortBy( obj, func );
_.sortBy = function(obj, iteratee, context) {
// 第3引数が入力されていない、第2引数が関数ならそのまま。
iteratee = cb(iteratee, context);
// _.map() は { value, index, iterateeを適用した値 } の配列を作る。
return _.pluck(_.map(obj, function(value, index, list) {
return {
value: value,
index: index,
criteria: iteratee(value, index, list)
};
// Array.sort()で上記で作成した配列をソートする。
}).sort(function(left, right) {
var a = left.criteria;
var b = right.criteria;
if (a !== b) {
if (a > b || a === void 0) return 1;
if (a < b || b === void 0) return -1;
}
return left.index - right.index;
// _.pluck() で value(Object)を抽出した配列を返す。
}), "value");
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var even = [ 2, 4, 6, 8, 10 ];
var odd = [ 1, 3, 5, 7, 9 ];
var func = function( val ){
return val % 2 == 0;
}
// re = true
var re = _.some( arr, func );
// re2 = true
var re2 = _.some( even, func );
// re3 = false
var re3 = _.some( odd, func );
_.some = _.any = function(obj, predicate, context) {
// 第3引数が入力されていない、第2引数が関数ならそのまま。
predicate = cb(predicate, context);
// 配列だったら keys = undefined 、Objectだったら keys は Object の key の配列。
var keys = !isArrayLike(obj) && _.keys(obj),
// length 抽出処理。
length = (keys || obj).length;
// 配列(Object)の各値を処理。
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
// 1回でも predicate の条件を満たした値の時にif( true )になるので true が返される。
if (predicate(obj[currentKey], currentKey, obj)) return true;
}
// 1度も条件を満たさなかったら false が返る。
return false;
};
var arr = [ 2, 4, 6 ];
// re = 3;
var re = _.size( arr );
var obj = {
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
};
// re = 3;
var re = _.size( obj );
_.size = function(obj) {
// obj が空だったら。
if (obj == null) return 0;
// obj が配列だったら配列の長さを。Object だったら Object の key の値の配列の長さを返す。
return isArrayLike(obj) ? obj.length : _.keys(obj).length;
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// [ 7, 1, 10, 5, 6, 4, 3, 8, 9, 2 ]
var re = _.shuffle( arr );
var obj = { one : 1, two : 2, three : 3 };
// [ 2, 1, 3 ]
var re = _.shuffle( obj );
_.shuffle = function(obj) {
// 引数「obj」が配列か arguments だったらそのまま。Object だったら Object の値の配列を作る。
var set = isArrayLike(obj) ? obj : _.values(obj);
var length = set.length;
// 結果を入れる配列を作る。
var shuffled = Array(length);
// 引数「obj」の値をランダムに入れ替えた配列を作るforループ。
for (var index = 0, rand; index < length; index++) {
rand = _.random(0, index);
// 配列のnullを排除しているif。shuffled[index] = shuffled[rand]; が空席を埋める機能を果たしている。
if (rand !== index) shuffled[index] = shuffled[rand];
shuffled[rand] = set[index];
}
return shuffled;
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = [ 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var re = _.rest( arr );
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = [ 4, 5, 6, 7, 8, 9, 10 ];
var re = _.rest( arr, 3 );
_.rest = _.tail = function(array, n, guard) {
// n == null か guard == true の時、slice.call( array, 1 );
// n が指定されている時、slice.call( array, n );
return slice.call(array, n == null || guard ? 1 : n );
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = 7
var re = _.sample( arr );
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = [ 2, 8, 3 ]
var re = _.sample( arr, 3 );
_.sample = function(obj, n, guard) {
// 第2引数が null または第3引数が undefined じゃない場合。
if (n == null || guard) {
// 第1引数が Object だった場合、Object の値だけの配列を作る。
if (!isArrayLike(obj)) obj = _.values(obj);
// length-1と0の間のランダムなindex値の値を返す。
return obj[_.random(obj.length - 1)];
}
// 配列の値の位置をランダムに入れ替え、それを最初からnまでのsliceした配列を返す。
return _.shuffle(obj).slice(0, Math.max(0, n));
};
var arr = [1, 2, 3, 4, 5, 6];
var func = function( num ){
return num % 2 == 0;
}
// [ 1, 3, 5 ]
var re = _.reject( arr, func );
_.reject = function(obj, predicate, context) {
// _.filter()とほぼ同じだが、第2引数の predicate が_.negate()に渡されるので条件を満たさない値のみとなる。
return _.filter(obj, _.negate(cb(predicate)), context);
};
var arr = [ 1 , 2 , 3 ];
var func = function(memo, value){
return memo + value;
}
// re = 6
var re = _.reduceRight( arr, func );
_.reduceRight = _.foldr = createReduce(-1);
//「dir = -1」が適用された関数を返す。
function createReduce(dir) {
// 下の返される関数で最後に呼ばれる関数。
function iterator(obj, iteratee, memo, keys, index, length) {
// 配列(obj)のそれぞれの値を処理するforループ。
for (; index >= 0 && index < length; index += dir) {
var currentKey = keys ? keys[index] : index;
memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
// 累積した結果を返す。
return memo;
}
// _.reduceRight()の引数はこの返される関数の引数。
return function(obj, iteratee, memo, context) {
// 引数 context がない場合は iteratee の関数がそのまま返る。
iteratee = optimizeCb(iteratee, context, 4);
// 引数 obj が Object なら key値 の配列を作成。
var keys = !isArrayLike(obj) && _.keys(obj),
// 引数 obj の length 抽出処理。
length = (keys || obj).length,
// _.reduceRight() は後ろから処理するため、index = length - 1。
index = dir > 0 ? 0 : length - 1;
// 引数が3未満なら 配列の最後の値をメモする。
if (arguments.length < 3) {
memo = obj[keys ? keys[index] : index];
index += dir;
}
return iterator(obj, iteratee, memo, keys, index, length);
};
}
// re = 38; ※0と100の間のランダムな数字になる。
var re = _.random( 0, 100 );
_.random = function(min, max) {
// 引数が1つだけだった場合。
if (max == null) {
max = min;
min = 0;
}
// 0 + Math.floor( Math.random() * ( 100 - 0 + 1 ) );
return min + Math.floor(Math.random() * (max - min + 1));
};
var arr = [ 1 , 2 , 3 ];
var func = function(memo, value){
return memo + value;
}
// re = 6
var re = _.reduce( arr, func );
_.reduce = _.foldl = _.inject = createReduce(1);
//「dir = 1」が適用された関数を返す。
function createReduce(dir) {
// 下の返される関数で最後に呼ばれる関数。
function iterator(obj, iteratee, memo, keys, index, length) {
// 配列(obj)のそれぞれの値を処理するforループ。
for (; index >= 0 && index < length; index += dir) {
var currentKey = keys ? keys[index] : index;
memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
// 累積した結果を返す。
return memo;
}
// _.reduce()の引数はこの返される関数の引数。
return function(obj, iteratee, memo, context) {
// 引数 context がない場合は iteratee の関数がそのまま返る。
iteratee = optimizeCb(iteratee, context, 4);
// 引数 obj が Object なら key 値の配列を作成。
var keys = !isArrayLike(obj) && _.keys(obj),
// 引数 obj の length 抽出処理。
length = (keys || obj).length,
// _.reduce() は前から処理するため、index = 0。
index = dir > 0 ? 0 : length - 1;
// 引数が3未満なら 配列の最初の値をメモする。
if (arguments.length < 3) {
memo = obj[keys ? keys[index] : index];
index += dir;
}
return iterator(obj, iteratee, memo, keys, index, length);
};
}
var obj = { name : "larry" };
// // re = "larry"
var re = _.property( "name" )( obj );
_.property = function(key) {
// 引数に入力された値を obj( 引数 )に部分適用した関数を返す。
return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
var obj = [
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1992,
author : "Michiru Yamane"
}
];
// [ 1991, 1992, 1992, 1992 ]
var re = _.pluck( obj, "year" );
// _.property(key)(val) の結果を配列として返す。
_.pluck = function(obj, key) {
return _.map(obj, _.property(key));
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var func = function( val ){
return val % 2 == 0;
};
// re = [ [2,4,6,8,10], [1,3,5,7,9] ];
var re = _.partition( arr, func );
var obj = [
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
}
];
var func = function( obj ){
return obj.year == 1992;
}
// re = [[
{"title":"Final Fantasy5 Original SoundTrack","year":1992,"author":"Nobuo Uematu"},
{"title":"Final Fantasy6 Original SoundTrack","year":1992,"author":"Nobuo Uematu"}
],[
{"title":"Final Fantasy4 Original SoundTrack","year":1991,"author":"Nobuo Uematu"},
{"title":"悪魔城ドラキュラX 月下の夜想曲","year":1994,"author":"Michiru Yamane"}
]];
var re = _.partition( obj, func );
_.partition = function(obj, predicate, context) {
// 第3引数が入力されていない、第2引数が関数ならそのまま。
predicate = cb(predicate, context);
var pass = [], fail = [];
// 第1引数「配列(Object)」の各値を第2引数の関数の条件によって振り分ける。
_.each(obj, function(value, key, obj) {
(predicate(value, key, obj) ? pass : fail).push(value);
});
return [pass, fail];
};
_.negate = function(predicate) {
// predicate関数の返す真偽値の反対を返す関数を返す。
return function() {
// return ! this.predicate( arguments ); thisはグローバルオブジェクト。
return !predicate.apply(this, arguments);
};
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = 1;
var re = _.min( arr );
var obj = [
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
}
];
var func = function( obj ){
return obj.year;
}
// re = { title: "Final Fantasy4 Original SoundTrack", year: 1991, author: "Nobuo Uematu" }
var re = _.min( obj, func );
_.min = function(obj, iteratee, context) {
var result = Infinity, lastComputed = Infinity,
value, computed;
if (iteratee == null && obj != null) {
// 第2引数「iteratee」が null で第1引数「obj」が null じゃない時。
// 第1引数「obj」が配列か arguments ならそのまま。Object なら key 配列を作成。
obj = isArrayLike(obj) ? obj : _.values(obj);
// 第1引数「obj」の各値で最小のものを調べるforループ。
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value < result) {
result = value;
}
}
} else {
// 第2引数「iteratee」が null じゃない時。
// 第3引数が入力されていない、第2引数が関数ならそのまま。
iteratee = cb(iteratee, context);
_.each(obj, function(value, index, list) {
// 第1引数「obj」の各値を第2引数「iteratee」で適用した値 = computed。
computed = iteratee(value, index, list);
// computed の値が比べられ最小値の値がresultになる。
if (computed < lastComputed || computed === Infinity && result === Infinity) {
result = value;
lastComputed = computed;
}
});
}
// 最小値の値 == result が返る。
return result;
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = 10;
var re = _.max( arr );
var obj = [
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
}
];
var func = function( obj ){
return obj.year;
}
// re = { title: "悪魔城ドラキュラX 月下の夜想曲", year: 1994, author: "Michiru Yamane" }
var re = _.max( obj, func );
_.max = function(obj, iteratee, context) {
var result = -Infinity, lastComputed = -Infinity,
value, computed;
if (iteratee == null && obj != null) {
// 第2引数「iteratee」が null で第1引数「obj」が null じゃない時。
// 第1引数「obj」が配列か arguments ならそのまま。Object なら key 配列を作成。
obj = isArrayLike(obj) ? obj : _.values(obj);
// 第1引数「obj」の各値で最大のものを調べるforループ。
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value > result) {
result = value;
}
}
} else {
// 第2引数「iteratee」が null じゃない時。
// 第3引数が入力されていない、第2引数が関数ならそのまま。
iteratee = cb(iteratee, context);
_.each(obj, function(value, index, list) {
// 第1引数「obj」の各値を第2引数「iteratee」で適用した値 = computed。
computed = iteratee(value, index, list);
// computed の値が比べられ最大値の値がresultになる。
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
result = value;
lastComputed = computed;
}
});
}
// 最大値の値 == result が返る。
return result;
};
_.matcher = _.matches = function(attrs) {
// attrs が Object だった時に「key : val」セットでコピーされる。
// _.extendOwn()はプロトタイプまではコピーしない。
attrs = _.extendOwn({}, attrs);
// _.matcher は部分適用した関数を返す。
return function(obj) {
// 引数(obj)に部分適用した attrs と同じ「key : val」があった場合trueを返す。
return _.isMatch(obj, attrs);
};
};
var arr = [ 1 , 2 , 3 ];
var func = function( val ){
return val * 3;
};
// re = [ 3, 6, 9 ]
var re = _.map( arr, func );
var obj = {
one : 1,
two : 2,
three : 3
};
var func = function( val, key ){
return val * 3;
};
// re = [ 3, 6, 9 ]
var re = _.map( obj, func );
_.map = _.collect = function(obj, iteratee, context) {
// 第3引数(context)があれば this に設定する。
// 第2引数(iteratee)が関数で第3引数(context)が undefined なら第2引数(iteratee)の関数のまま。
iteratee = cb(iteratee, context);
// obj が配列じゃなかったら、objのkeyの配列を抽出。
var keys = !isArrayLike(obj) && _.keys(obj),
// objのlength抽出。
length = (keys || obj).length,
results = Array(length);
// objの各値に関数を適用し、結果を配列にする処理。
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = 10;
var re = _.last( arr );
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = [ 6, 7, 8, 9, 10 ];
var re = _.last( arr, 5 );
_.last = function(array, n, guard) {
// 第1引数が null だったら
if (array == null) return void 0;
// 第2引数が null か, 第3引数 が false だったら第1引数「配列」の最後の値を返す。
if (n == null || guard) return array[array.length - 1];
// 第2引数が指定されていた時、配列の最初から「array.length - n」の数だけ削除した残りの配列が返る。
return _.rest(array, Math.max(0, array.length - n));
};
var arr001 = [5, 1, 7];
var arr002 = [3, 2, 1]
// re = [ [1,5,7], [1,2,3] ]
var re = _.invoke( [arr001, arr002], "sort");
var arr001 = [5, 1, 7];
var arr002 = [3, 2, 1]
// re2 = [ 5, 3 ]
var re2 = _.invoke( [arr001, arr002], "shift");
var arr001 = [5, 1, 7];
var arr002 = [3, 2, 1]
// re3 = [ 7, 1 ]
var re3 = _.invoke( [arr001, arr002], "pop");
_.invoke = function(obj, method) {
// arguments.slice( 2 ); ほとんど args = [ ]; になる。
var args = slice.call(arguments, 2);
// method が関数かどうか確認される。_内で定義されている文字列でないと isFunc = true にならない。
var isFunc = _.isFunction(method);
return _.map(obj, function(value) {
// isFunc = true なら第1引数「obj」の各値を this、引数を args とした method 処理が行われる。
var func = isFunc ? method : value[method];
return func == null ? func : func.apply(value, args);
});
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
var re = _.initial( arr );
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = [ 1, 2, 3, 4, 5 ];
var re = _.initial( arr, 5 );
_.initial = function(array, n, guard) {
// 第2引数が指定されていた時、第2引数で指定された数だけ後ろから削除された第1引数 array が返る。
return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var arr2 = [10, 20, 30, NaN, 40, 50];
var num = 5;
var num2 = NaN;
var num3 = 13;
// re = 4
var re = _.indexOf( arr, num );
// re2 = 3
var re2 = _.indexOf( arr2, num2, 3 );
// re3 = -1
var re3 = _.indexOf( arr, num3 );
_.indexOf = function(array, item, isSorted) {
var i = 0, length = array && array.length;
// 第3引数がの型が数字だったら、
if (typeof isSorted == "number") {
// 第3引数が0以上の場合はそのまま i に代入される。
i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
// 第3引数の型が数字以外で true の場合
} else if (isSorted && length) {
// 第1引数の配列の中で第2引数を入れる位置のindex値を i に代入。
i = _.sortedIndex(array, item);
return array[i] === item ? i : -1;
}
// if (item !== item) は item = NaN の時 if 文が実行される。
if (item !== item) {
// sliceされた配列の中に NaN が含まれていたら index値を返す。
return _.findIndex(slice.call(array, i), _.isNaN);
}
// 第1引数の配列の中に第2引数があったら、配列のindex値を返す。
for (; i < length; i++) if (array[i] === item) return i;
return -1;
};
var arr = [ 1.3, 2.1, 2.4 ];
var func = function( num ){
return Math.floor( num );
}
// re = {"1":1.3,"2":2.4};
var re = _.indexBy( arr, func );
var obj = [
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
}
];
var func = function( obj ){
return obj.year;
}
// re = {
"1994":{"title":"悪魔城ドラキュラX 月下の夜想曲","year":1994,"author":"Michiru Yamane"},
"1992":{"title":"Final Fantasy6 Original SoundTrack","year":1992,"author":"Nobuo Uematu"},
"1991":{"title":"Final Fantasy4 Original SoundTrack","year":1991,"author":"Nobuo Uematu"}
}
var re = _.indexBy( obj, func );
// group()の最後に function(result, value, key) { } が呼び出される。
_.indexBy = group(function(result, value, key) {
result[key] = value;
});
var group = function(behavior) {
// _.indexBy() の引数は以下の返される関数に代入される。
return function(obj, iteratee, context) {
var result = {};
// 第3引数が入力されていない、第2引数が関数ならそのまま。
iteratee = cb(iteratee, context);
_.each(obj, function(value, index) {
// 第1引数の各値(Object)に第2引数の関数が適用された結果。
var key = iteratee(value, index, obj);
// group() の引数がセットされ関数として機能する。
behavior(result, value, key);
});
return result;
};
};
var obj = { name : "larry" };
// re = { name : "larry" };
var re = _.identity( obj );
// 引数を返す関数。
_.identity = function(value) {
return value;
};
var obj = {
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
}
// re = true;
var re = _.has( obj, "title" );
_.has = function(obj, key) {
// _内で hasOwnProperty = ObjProto.hasOwnProperty; が宣言されている。
// obj が空でない場合は、key があれば true が返される。
return obj != null && hasOwnProperty.call(obj, key);
};
var arr = [ 1.3, 2.1, 2.4 ];
var func = function( num ){
return Math.floor( num );
}
// re = { "1" : [1.3], "2" : [2.1,2.4] };
var re = _.groupBy( arr, func );
var obj = [
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
}
];
var func = function( obj ){
return obj.year;
}
// re = {
"1994":[{"title":"悪魔城ドラキュラX 月下の夜想曲","year":1994,"author":"Michiru Yamane"}],
"1992":[{"title":"Final Fantasy5 Original SoundTrack","year":1992,"author":"Nobuo Uematu"},
{"title":"Final Fantasy6 Original SoundTrack","year":1992,"author":"Nobuo Uematu"}],
"1991":[{"title":"Final Fantasy4 Original SoundTrack","year":1991,"author":"Nobuo Uematu"}]
}
var re = _.groupBy( obj, func );
// group()の最後に function(result, value, key) { } が呼び出される。
_.groupBy = group(function(result, value, key) {
// 「result」Object の中に key のgroup毎の配列に値が分けられる。
if (_.has(result, key)) result[key].push(value); else result[key] = [value];
});
var group = function(behavior) {
// _.groupBy() の引数は以下の返される関数に代入される。
return function(obj, iteratee, context) {
var result = {};
// 第3引数が入力されていない、第2引数が関数ならそのまま。
iteratee = cb(iteratee, context);
_.each(obj, function(value, index) {
// 第1引数の各値(Object)に第2引数の関数が適用された結果。
var key = iteratee(value, index, obj);
// group() の引数がセットされ関数として機能する。
behavior(result, value, key);
});
return result;
};
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = 1;
var re = _.first( arr );
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = [ 1, 2, 3, 4, 5 ];
var re = _.first( arr, 5 );
_.first = _.head = _.take = function(array, n, guard) {
// 第1引数が null だったら
if (array == null) return void 0;
// 第2引数が null か, 第3引数 が false だったら第1引数「配列」の最初の値を返す。
if (n == null || guard) return array[0];
// 第1引数「配列」を第2引数で指定された数だけ後ろから削除され、残り配列が返る。
return _.initial(array, array.length - n);
};
var obj = [
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1992,
author : "Michiru Yamane"
}
];
var pre = { year : 1992 };
// { title : "Final Fantasy5 Original SoundTrack", year : 1992, author : "Nobuo Uematu" }
var re = _.findWhere( obj, pre );
_.findWhere = function(obj, attrs) {
// _.find()にobjと_.matcher(同じプロパティと値があるかを判別する部分適用した関数)を渡す。
// 条件に該当する最初の値を返す。
return _.find(obj, _.matcher(attrs));
};
var arr = [ 7, 1, 6, 7, 4 ];
var func = function(num){
return num % 2 == 0;
}
// re = 4
var re = _.findLastIndex( arr, func );
_.findLastIndex = createIndexFinder(-1);
function createIndexFinder(dir) {
// _.findLastIndex() の引数が適用される関数。
return function(array, predicate, context) {
// 第3引数が入力されていない、第2引数が関数ならそのまま。
predicate = cb(predicate, context);
// 第1引数の長さ抽出。
var length = array != null && array.length;
// index = length - 1;
var index = dir > 0 ? 0 : length - 1;
// 第2引数の関数の条件を満たしていた配列のindex値が返される。
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
// 各値が条件を満たしていなかった場合、「-1」が返される。
return -1;
};
}
var obj = { js01: "Underscore JS", js02 : "jQuery" };
var func = function( val, key, obj ){
if( key == "js01" ) return val;
}
// re = js01
var re = _.findKey( obj, func );
_.findKey = function(obj, predicate, context) {
// 第3引数が入力されていない、第2引数が関数ならそのまま。
predicate = cb(predicate, context);
// Objectのkey値のみの配列を作成。ローカル変数keyの宣言。
var keys = _.keys(obj), key;
// Objectの各値が第2引数の関数に適用されるforループ。
for (var i = 0, length = keys.length; i < length; i++) {
key = keys[i];
// 第2引数の関数の条件を満たしていたObjectの最初のkey値が返される。
if (predicate(obj[key], key, obj)) return key;
}
};
var arr = [ 7, 1, 6, 7, 4 ];
var func = function(num){
return num % 2 == 0;
}
// re = 2
var re = _.findIndex( arr, func );
_.findIndex = createIndexFinder(1);
function createIndexFinder(dir) {
// _.findIndex() の引数が適用される関数。
return function(array, predicate, context) {
// 第3引数が入力されていない、第2引数が関数ならそのまま。
predicate = cb(predicate, context);
// 第1引数の長さ抽出。
var length = array != null && array.length;
// index = 0;
var index = dir > 0 ? 0 : length - 1;
// 第2引数の関数の条件を満たしていた配列の最初のindex値が返される。
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
// 各値が条件を満たしていなかった場合、「-1」が返される。
return -1;
};
}
var arr = [ 7, 1, 6, 7, 4 ];
var func = function(num){
return num % 2 == 0;
}
// re = 6
var re = _.find( arr, func );
_.find = _.detect = function(obj, predicate, context) {
var key;
if (isArrayLike(obj)) {
// objが配列なら_.findIndex()で条件を満たしている値のindex値が返される。
key = _.findIndex(obj, predicate, context);
} else {
// objがObjectなら_.findKey()で条件を満たしている値のindex値が返される。
key = _.findKey(obj, predicate, context);
}
// 条件を満たしているobjの最初の値が返される。
if (key !== void 0 && key !== -1) return obj[key];
};
var arr = [1, 2, 3, 4, 5, 6];
var func = function( num ){
return num % 2 == 0;
}
// [ 2, 4, 6 ]
var re = _.filter( arr, func );
_.filter = _.select = function(obj, predicate, context) {
var results = [ ];
// 第3引数が入力されていない、第2引数が関数ならそのまま。
predicate = cb(predicate, context);
// objのそれぞれの値を関数で処理。条件を満たしている値のみ results に push される。
_.each(obj, function(value, index, list) {
if (predicate(value, index, list)) results.push(value);
});
// 条件を満たしている値のみの配列が返される。
return results;
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var even = [ 2, 4, 6, 8, 10 ];
var func = function( val ){
return val % 2 == 0;
}
// re = false
var re = _.every( arr, func );
// re2 = true
var re2 = _.every( even, func );
_.every = _.all = function(obj, predicate, context) {
// 第3引数が入力されていない、第2引数が関数ならそのまま。
predicate = cb(predicate, context);
// 配列だったら keys = undefined 、Objectだったら keys は Object の key の配列。
var keys = !isArrayLike(obj) && _.keys(obj),
// length 抽出処理。
length = (keys || obj).length;
// 配列(Object)の各値を処理。
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
// predicate の条件を満たしていない値の時にif( true )になるので false が返される。
if (!predicate(obj[currentKey], currentKey, obj)) return false;
}
return true;
};
var arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var func = function( val ){
return val % 2 == 0 ? "even" : "odd";
}
// re = { "odd" : 5, "even" : 5 };
var re = _.countBy( arr, func );
var obj = [
{
title : "悪魔城ドラキュラX 月下の夜想曲",
year : 1994,
author : "Michiru Yamane"
},
{
title : "Final Fantasy5 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy4 Original SoundTrack",
year : 1991,
author : "Nobuo Uematu"
},
{
title : "Final Fantasy6 Original SoundTrack",
year : 1992,
author : "Nobuo Uematu"
}
];
var func = function( obj ){
return obj.year;
}
// re = {"1994":1,"1992":2,"1991":1};
var re = _.countBy( obj, func );
// group()の最後に function(result, value, key) { } が呼び出される。
_.countBy = group(function(result, value, key) {
// result に key のプロパティがあったら、result[key]++;
if (_.has(result, key)) result[key]++; else result[key] = 1;
});
var group = function(behavior) {
// _.countBy() の引数は以下の返される関数に代入される。
return function(obj, iteratee, context) {
var result = {};
// 第3引数が入力されていない、第2引数が関数ならそのまま。
iteratee = cb(iteratee, context);
_.each(obj, function(value, index) {
// 第1引数の各値( obj )に第2引数の関数が適用された結果。
var key = iteratee(value, index, obj);
// group() の引数がセットされ関数として機能する。
behavior(result, value, key);
});
return result;
};
};
var greet = function(name){
return "hi: " + name;
};
var exclaim = function(statement){
return statement.toUpperCase() + "!";
};
var welcome = _.compose( greet, exclaim );
// "hi: MOE!"
console.log( welcome("moe") );
_.compose = function() {
// 引数全部
var args = arguments;
// 引数の数 - 1
var start = args.length - 1;
// _.compose自体は関数を返す。
return function() {
var i = start;
// this.args[start]( 返される関数のarguments );(ブラウザなら window = this )
var result = args[start].apply(this, arguments);
// 引数がなくなるまでの whileループ処理。グローバルオブジェクトをthisにして前の関数の結果を引数に関数処理を繰り返す。
while (i--) result = args[i].call(this, result);
return result;
};
};
var arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
// re = true
var re = _.contains( arr, 10 );
// re2 = false
var re2 = _.contains( arr, 50 );
// re3 = false
var re3 = _.contains( arr, 0, 5 );
_.contains = _.includes = _.include = function(obj, target, fromIndex) {
// obj が配列と arguments でなかったら、obj の値を抽出した配列を obj に代入する。
if (!isArrayLike(obj)) obj = _.values(obj);
// 第3引数 fromIndex は型が数字で undefined じゃなかったら fromIndex がそのまま渡され、数字でない場合等は false が渡され、
// _.indexOf( obj, target, fromIndex ) が実行される。
return _.indexOf(obj, target, typeof fromIndex == "number" && fromIndex) >= 0;
};
// MAX_ARRAY_INDEX = 9007199254740991
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var isArrayLike = function(collection) {
// collection が false 以外だったら length = collection.length;
var length = collection && collection.length;
// 真偽値を返す。
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
var arr = [ 1 , 2 , 3 ];
var func = function( val ){
console.log(val);
};
// arr の各値がコンソールに出力される。
_.each( arr, func );
var obj = {
one : 1,
two : 2,
three : 3
};
var func = function( val ){
console.log(val);
};
// obj の各値がコンソールに出力される。
_.each( obj, func );
_.each = _.forEach = function(obj, iteratee, context) {
// 第2引数が関数かどうかチェックされる。詳細は optimizeCb 関数へ
// 第3引数 = undefined で 第2引数の型が function なら iteratee = 第2引数のまま。
iteratee = optimizeCb(iteratee, context);
var i, length;
// isArrayLike(obj) は obj が 配列 か arguments の時、true。
if (isArrayLike(obj)) {
// 配列 と arguments の時の処理。
// 関数に 配列の値、index値、配列自身を渡す。
for (i = 0, length = obj.length; i < length; i++) {
iteratee(obj[i], i, obj);
}
} else {
// Object の時の処理。
// Object の key のみの配列を抽出。
var keys = _.keys(obj);
// 第2引数に Objectの値、Objectのkey、Object自身を渡す。
for (i = 0, length = keys.length; i < length; i++) {
iteratee(obj[keys[i]], keys[i], obj);
}
}
return obj;
};
おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>本物のアップライトピアノとかグランドピアノの弾きごこち。たぶんこの鍵盤弾きこなせるならアコースティックピアノ、各メーカーの主要な鍵盤は対応可能。練習には最適な鍵盤だと思う。夜も周りに迷惑かけず弾けるし。
KORGの親会社はYAMAHA。ベーゼンドルファーの親会社もYAMAHA。SGX-1音源でサンプリングされている KRONOS German Grand のピアノの音も自前で作ってる事になる。PCM音源はその性質上、生楽器を録音して使う事もあるため権利関係から考えるとハードルが高い。 ただ対価を支払ってPCM音源を作ってるメーカーもある。ROLAND はD-50でウェーブシーケンスしている音色も含まれているが、ウェーブシーケンスを搭載したシンセサイザーは作っていない。WAVESTATION は元々シーケンシャルサーキット社の開発メンバーも開発に参加していた。 シーケンシャルサーキット社はPROPHET VSを開発している。各社ウェーブテーブルシンセシスの影響が大きかったのだろう。YAMAHAはシーケンシャルサーキット社を買収している。YAMAHAは実物楽器も色々作ってる。
純粋にエレクトリックピアノが欲しいならSV−1の方が良い気がする。KRONOSのが悪いんじゃなくて普通で(ローズとかのサンプリングだし、ライセンスどうしたんだろう?)SV-1の昔公開されていたDEMO音源のエレピの音が非常に良かった。
今のところプラグインエディターの必要性を感じてないほど、タッチパネルが使いやすい。プラグインエディターは全然使っていないので感想が書けない。
KRONOS X に搭載されているプリセット音色を使ってクラシックの曲などを演奏しています。主にMOD-7音源とSTR-1音源。
(Mix、 Mastering処理はしていますが、音色そのものは何も変更していない。)
(Mix、 Mastering処理はしていますが、音色そのものは何も変更していない。)
おすすめ
]]>(Mix、 Mastering処理はしていますが、音色そのものは何も変更していない。)
おすすめ
]]>(Mix、 Mastering処理はしていますが、音色そのものは何も変更していない。)
おすすめ
]]>(Mix、 Mastering処理はしていますが、音色そのものは何も変更していない。)
おすすめ
]]>おすすめ
]]>Muzie の方がニコニコより音質良いかも。 Muzie
]]>おすすめ
]]>おすすめ
]]>おすすめ
]]>Muzie の方がニコニコより音質良いかも。 Muzie
]]>おすすめ
]]>Muzie の方がニコニコより音質良いかも。 Muzie
]]>おすすめ
]]>Muzie の方がニコニコより音質良いかも。 Muzie
]]>おすすめ
]]>Muzie の方がニコニコより音質良いかも。 Muzie
]]>おすすめ
]]>おすすめ
]]>]]>
■ライブ演奏目録(順番はうる覚え)
鏡の国
Monday, Tuesday
ターミナル
きれいな感情
虹色の惑星
The Tree of Life
ノルブリンカ
印象
太陽の塔
Adesso e forutuna ~ 炎と永遠 ~
夜気
Lhasa
瓦礫の楽園
降るプラチナ
鉱石ラジオ
Orient Line
Haleakalā
花かんむり
蜜の夜明け(狼と香辛料オープニングテーマ)
At Eden
この布陣でのバンドサウンドは凄く良かったです!!
オープニングを飾った「鏡の国」、「Monday, Tuesday」はアルバムと編曲的には同じですが、少しモタった感じで凄くよかったです。
澄み渡る昭乃さんの声が響き、ASA-CHANGの不思議な打楽器の「ノルブリンカ」 (ここらへんは鳥肌もの)
そして等さんと昭乃さんだけの「Adesso e forutuna ~ 炎と永遠 ~」は昔から聴いているはずなのに胸を熱くさせられました。
等さんのマンドリア(?)の音がなんとも・・・・・・・・・音的にはシャ・リオンのオープニングの音に近いかな。
白血病を乗り越えてきた少女のエピソードと共に紹介され、
等さんのアドリブ的な演奏とASA-CHANGの打楽器、マー君のバイオリンでアルバムの雰囲気を醸し出す「Lhasa」(ここらへんも鳥肌もの)
そしてノリノリで保刈さんがギターを弾く「Orient Line」(あんな保刈さん初めてだ(笑))
そして柚楽弥衣さんとの共演の「Haleakalā」(7人総出での演奏はただただ圧巻)
昭乃さんピアノと弥衣さんvoiceの「花かんむり」
新曲の「蜜の夜明け」
今回は座席的にも恵まれ、(アリーナ、センターの前から7列目)音響環境は物凄く良かったです!! 出来れば、もう一回行きたい。もしくはライブDVDでないかな~
あとライブパンフレット購入。こちらは次回再度レポートします。
おすすめ
]]>おすすめ
]]>
■演奏楽曲
1:赤い砂 白い花(アカペラ)
2:雨の言葉 (新)
3:遥かなロンド
4:at EDEN
5:レインフォレスト
6:メロディ
7:きれいな感情
8:バニラ
9:太陽の塔
10:水
11:黄昏は未来で待つ
12:ガレキの楽園
13:降るプラチナ
14:鉱石ラジオ
15:アトムの光
16:VOICES
アンコール
金の波千の波
花かんむり
■演奏楽曲
1:Airplane
2:Trance Transistor Table Radio
3:花のかたち
4:Flower
5:Orange Noel
6:サリーのビー玉
7:バニラ
8:Pool
9:Happiness is Here (オケのみ)
10:風と鳥と空 ~reincarnation~
11:鉱石ラジオ
12:懐かしい宇宙
13:覚醒都市
14:砂の岸辺
15:遙かなロンド
16:at Eden
17:Happiness is Here
18:Princess of winter