Zeptoにおけるオブジェクト拡張機能の実装

型判定の実装

const typeMapping = {};
const typeString = typeMapping.toString;
const Z = {};

function getType(value) {
  return value == null ? String(value) : typeMapping[typeString.call(value)] || "object";
}

function checkObject(value) {
  return getType(value) == "object";
}

function checkPlainObject(value) {
  return checkObject(value) && !isWindow(value) && 
         Object.getPrototypeOf(value) === Object.prototype;
}

function checkArray(value) {
  return Array.isArray(value) || value instanceof Array;
}

extend関数の仕組み

Zeptoの拡張機能では、まず内部で使用されるextend関数が定義されています。この関数は3つのパラメータを受け取ります:target, source, deep。targetは拡張対象のオブジェクト、sourceは拡張元のオブジェクト、deepは深い拡張を行うかどうかを示します。

extend関数では、深い拡張が指定された場合でも再帰関数を通じて拡張が行われ、最終的にはtarget[key] = source[key]という形でプロパティが設定されます。違いは拡張の深さにあります。

浅い拡張の例

const obj1 = {
  name: "original",
  data: {
    name: "nested",
    alias: "old"
  }
};

// 浅い拡張
extend(obj1, {name: "new", data: {name: "updated", data: {name: "deep"}}});
console.log(obj1);

deepパラメータを使用しない場合、オブジェクトの第一階層のプロパティのみが直接拡張・上書きされます。

深い拡張の例

// 深い拡張
extend(obj1, {name: "new", data: {name: "updated", data: {name: "deep"}}}, true);
console.log(obj1);

深い拡張を使用すると、元のオブジェクト内の対応する値が変更されずに、ネストされたオブジェクトも適切に拡張されます。

$.extendの機能

$.extendは外部から使用可能な拡張関数で、$オブジェクトに直接定義されています。Zeptoのプラグイン拡張は$.extendを通さなくてもZeptoオブジェクトに追加できます。これはZeptoのdom.__proto__ = $.fn, zepto.Z.prototype = $.fnという設計と、$が返されるためです。

$.extend関数は内部でargumentsを使用しているため、パラメータ数に制限はありません。深い拡張を行いたい場合は、最初のパラメータをtrueに設定します。

複数オブジェクトの浅い拡張

const obj2 = $.extend(obj1, 
  {name: "first", data: {name: "nested1", data: {name: "deep1"}}},
  {name: "second"}
);
console.log(obj2);

複数オブジェクトの深い拡張

const obj3 = $.extend(true, obj1,
  {name: "first", data: {name: "nested1", data: {name: "deep1"}}},
  {name: "second", data: {name: "nested2"}}
);
console.log(obj3);

タグ: zepto javascript オブジェクト拡張 関数プログラミング ライブラリ開発

8月14日 08:04 投稿