ホームページ ウェブフロントエンド jsチュートリアル JavaScript でのオブジェクトのディープコピー

JavaScript でのオブジェクトのディープコピー

Jan 03, 2017 pm 03:49 PM
モジュール開発

モジュール開発とは何ですか?

フロントエンド開発では、最初は、スクリプト タグに数十行または数百行のコードを埋め込むことで、いくつかの基本的なインタラクティブ効果を実現できましたが、その後、js が注目を集め、jQuery、Ajax、Node.Js など、広く使用されるようになりました。 MVC や MVVM の助けを借りて、フロントエンド開発にも注目が集まっており、フロントエンド プロジェクトはますます複雑になってきていますが、JavaScript はコードを整理するのに明確な助けを提供しません。モジュールはおろか、クラスの概念さえありません。では、モジュールとは何でしょうか?

モジュールは、特定の機能を実装するファイルです。モジュールを使用すると、必要な機能に必要なモジュールをより便利に使用できます。モジュール開発は特定の規範に従う必要があります。そうしないと、すべてが台無しになってしまいます。

AMD 仕様に従って、define を使用してモジュールを定義し、require を使用してモジュールを呼び出すことができます。

現在、主によく使われている js モジュール仕様は CommonJS と AMD の 2 つです。

AMD仕様

AMDとは、Asynchronous Module Definitionのことで、中国語名は「非同期モジュール定義」を意味します。ブラウザ側でのモジュール開発の仕様であり、サーバー側ではCommonJS

モジュールが非同期でロードされ、モジュールのロードは後続のステートメントの実行に影響を与えません。特定のモジュールに依存するすべてのステートメントはコールバック関数に配置されます。

AMD は、RequireJS のプロモーション プロセス中のモジュール定義の標準化された出力です。

define() 関数

AMD 仕様では、グローバル変数である関数 define が 1 つだけ定義されています。関数の説明は次のとおりです:

define(id?, dependencies?, factory);
ログイン後にコピー

パラメータの説明:

id: 定義内のモジュールの名前を参照します。このパラメータが指定されていない場合、モジュールの名前はデフォルトで使用されます。モジュールローダーによって要求された指定されたスクリプトの名前。このパラメータを指定する場合、モジュール名は「トップレベル」で絶対的な名前である必要があります (相対名は許可されません)。

依存関係: 現在のモジュールが依存する配列リテラルであり、モジュールによって定義されたモジュールによって識別されます。
依存関係パラメーターはオプションです。このパラメーターを省略した場合、デフォルトで ["require", "exports", "module"] になります。ただし、ファクトリ メソッドの長さ属性が 3 未満の場合、ローダーは関数の長さ属性で指定された引数の数でファクトリ メソッドを呼び出すことを選択します。

ファクトリメソッドファクトリ、モジュールは実行される関数またはオブジェクトを初期化します。関数の場合は、一度だけ実行する必要があります。それがオブジェクトの場合、このオブジェクトはモジュールの出力値である必要があります。

モジュール名の形式

モジュール名は、定義内でモジュールを一意に識別するために使用されます。依存関係配列でも使用されます。

モジュール名はスラッシュで区切られた意味のある単語の文字列です
単語はキャメルケースである必要があります。 、または「.」、「..」
モジュール名には「.js」形式のファイル拡張子は使用できません
モジュール名は「相対」または「トップレベル」にすることができます。最初の文字が「.」または「..」の場合、それは相対モジュール名です
最上位モジュール名は、ルート名前空間の概念モジュールから解決されます
相対モジュール名は、書き込まれて呼び出されるモジュールから解決されます「require」で

requireとexportsを使う

require、exportsと「beta」という名前のモジュールを使って「alpha」という名前のモジュールを作成します:

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
   exports.verb = function() {
     return beta.verb();
     //Or:
     return require("beta").verb();
   }
 });
ログイン後にコピー

require APIの紹介: https://github. com/amdjs/amdjs-api/wiki/require

AMD 仕様の中国語版: https://github.com/amdjs/amdjs-api/wiki/AMD-(%E4%B8%AD%E6%96%87 %E7%89% 88)

現在、AMD を実装するライブラリには、RequireJS、curl、Dojo、Nodules などが含まれます。

CommonJS仕様

CommonJSはサーバーサイドモジュールの仕様であり、Node.jsはこの仕様を採用しています。 Node.JS は、js モジュール性の概念を初めて採用しました。

CommonJS 仕様によれば、単一のファイルがモジュールです。各モジュールには個別のスコープがあります。つまり、モジュール内で定義された変数は、グローバル オブジェクトの属性として定義されない限り、他のモジュールから読み取ることができません。

モジュール変数をエクスポートする最良の方法は、 module.exports オブジェクトを使用することです。

var i = 1;
var max = 30;
 
module.exports = function () {
 for (i -= 1; i++ < max; ) {
  console.log(i);
 }
 max *= 1.1;
};
ログイン後にコピー

上記のコードは、モジュールの外部通信と内部通信の間のブリッジである module.exports オブジェクトを通じて関数を定義します。

require メソッドを使用してモジュールをロードします。このメソッドはファイルを読み取って実行し、最後にファイル内の module.exports オブジェクトを返します。

CommonJS 仕様: http://javascript.ruanyifeng.com/nodejs/commonjs.html

RequireJS と SeaJS

RequireJS は、AMD 仕様の創設者でもある James Burke によって作成されました。

define メソッドはモジュールを定義するために使用されます。RequireJS では、各モジュールを別のファイルに配置する必要があります。

RequireJS と Sea.js は両方ともモジュール ローダーであり、モジュール開発の概念を提唱しており、その中心的な価値は JavaScript のモジュール開発をシンプルかつ自然にすることです。

SeaJS と RequireJS の最大の違い:

SeaJS のモジュールに対する態度は遅延実行ですが、RequireJS のモジュールに対する態度は事前実行です

理解できませんか?写真とテキスト付きのこの記事をご覧ください: http://www.douban.com/note/283566440/

RequireJS API: http://www.requirejs.cn/docs/api.html

RequireJS の使用法: http://www.ruanyifeng.com/blog/2012/11/require_js.html

requireJS を使用する理由

试想一下,如果一个网页有很多的js文件,那么浏览器在下载该页面的时候会先加载js文件,从而停止了网页的渲染,如果文件越多,浏览器可能失去响应。其次,要保证js文件的依赖性,依赖性最大的模块(文件)要放在最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。

RequireJS就是为了解决这两个问题而诞生的:

(1)实现js文件的异步加载,避免网页失去响应;
(2)管理模块之间的依赖性,便于代码的编写和维护。

RequireJS文件下载:http://www.requirejs.cn/docs/download.html

AMD和CMD

CMD(Common Module Definition) 通用模块定义。该规范明确了模块的基本书写格式和基本交互规则。该规范是在国内发展出来的。AMD是依赖关系前置,CMD是按需加载。

在 CMD 规范中,一个模块就是一个文件。代码的书写格式如下:

define(factory);
ログイン後にコピー

factory 为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。factory 方法在执行时,默认会传入三个参数:require、exports 和 module:

define(function(require, exports, module) {
 // 模块代码
});
ログイン後にコピー

require是可以把其他模块导入进来的一个参数,而export是可以把模块内的一些属性和方法导出的。

CMD规范地址:https://github.com/seajs/seajs/issues/242

AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。

AMD:提前执行(异步加载:依赖先执行)+延迟执行
CMD:延迟执行(运行到需加载,根据顺序执行)
CMD 推崇依赖就近,AMD 推崇依赖前置。看如下代码:

// CMD
define(function(require, exports, module) {
var a = require(&#39;./a&#39;)
a.doSomething()
// 此处略去 100 行
var b = require(&#39;./b&#39;) // 依赖可以就近书写
b.doSomething()
// ...
})
 
// AMD 默认推荐的是
define([&#39;./a&#39;, &#39;./b&#39;], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
})
ログイン後にコピー

另外一个区别是:

AMD:API根据使用范围有区别,但使用同一个api接口
CMD:每个API的职责单一
AMD的优点是:异步并行加载,在AMD的规范下,同时异步加载是不会产生错误的。
CMD的机制则不同,这种加载方式会产生错误,如果能规范化模块内容形式,也可以

jquery1.7以上版本会自动模块化,支持AMD模式:主要是使用define函数,sea.js虽然是CommonJS规范,但却使用了define来定义模块
所以jQuery已经自动模块化了

seajs.config({
&#39;base&#39;:&#39;/&#39;,
&#39;alias&#39;:{
  &#39;jquery&#39;:&#39;jquery.js&#39;//定义jQuery文件
}
});
ログイン後にコピー

define函数和AMD的define类似:

define(function(require, exports, module{
   //先要载入jQuery的模块
   var $ = require(&#39;jquery&#39;);
   //然后将jQuery对象传给插件模块
   require(&#39;./cookie&#39;)($);
   //开始使用 $.cookie方法
});
ログイン後にコピー

sea.js如何使用?

引入sea.js的库

如何变成模块?

define

3.如何调用模块?

-exports
-sea.js.use
4.如何依赖模块?

-require

<script type="text/javascript">
    define(function (require,exports,module) {
      //exports : 对外的接口
      //requires : 依赖的接口
      require(&#39;./test.js&#39;);//如果地址是一个模块的话,那么require的返回值就是模块中的exports
    })
</script>
ログイン後にコピー

sea.js 开发实例

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>鼠标拖拽的模块化开发实践</title>
<style type="text/css">
#div1{ width:200px; height:200px; background:black; position:absolute; display:none;}
#div2{ width:30px; height:30px; background:yellow; position:absolute; bottom:0; right:0;}
#div3{ width:100px; height:100px; background:blue; position:absolute; right:0; top:0;}
</style>
<script type="text/javascript" src="./sea.js"></script>
<script type="text/javascript">
   
//A同事 :
seajs.use(&#39;./main.js&#39;);
   
</script>
</head>
 
<body>
<input type="button" value="确定" id="input1" />
<div id="div1">
  <div id="div2"></div>
</div>
<div id="div3"></div>
</body>
</html>
ログイン後にコピー

A同事

//A同事写的main.js:
 
define(function (require,exports,module) {
  var oInput = document.getElementById(&#39;input1&#39;);
  var oDiv1 = document.getElementById(&#39;div1&#39;);
  var oDiv2 = document.getElementById(&#39;div2&#39;);
  var oDiv3 = document.getElementById(&#39;div3&#39;);
 
  require(&#39;./drag.js&#39;).drag(oDiv3);
  oInput.onclick = function () {
    oDiv1.style.display = &#39;block&#39;;
    require(&#39;./scale.js&#39;).scale(oDiv1,oDiv2);
 
    require.async(&#39;./scale.js&#39;, function (ex) {
      ex.scale(oDiv1,oDiv2);
    })
  }
});
ログイン後にコピー

B同事

//B同事写的drag.js:
 
define(function(require,exports,module){
   
  function drag(obj){
    var disX = 0;
    var disY = 0;
    obj.onmousedown = function(ev){
      var ev = ev || window.event;
      disX = ev.clientX - obj.offsetLeft;
      disY = ev.clientY - obj.offsetTop;
       
      document.onmousemove = function(ev){
        var ev = ev || window.event;
 
 
         var L = require(&#39;./range.js&#39;).range(ev.clientX - disX , document.documentElement.clientWidth - obj.offsetWidth , 0 );
         var T = require(&#39;./range.js&#39;).range(ev.clientY - disY , document.documentElement.clientHeight - obj.offsetHeight , 0 );
 
         
        obj.style.left = L + &#39;px&#39;;
        obj.style.top = T + &#39;px&#39;;
      };
      document.onmouseup = function(){
        document.onmousemove = null;
        document.onmouseup = null;
      };
      return false;
    };
  }
   
  exports.drag = drag;//对外提供接口
   
});
ログイン後にコピー

C同事

//C同事写的scale.js:
 
define(function(require,exports,module){
   
   
  function scale(obj1,obj2){
    var disX = 0;
    var disY = 0;
    var disW = 0;
    var disH = 0;
     
    obj2.onmousedown = function(ev){
      var ev = ev || window.event;
      disX = ev.clientX;
      disY = ev.clientY;
      disW = obj1.offsetWidth;
      disH = obj1.offsetHeight;
       
      document.onmousemove = function(ev){
        var ev = ev || window.event;
         
        var W = require(&#39;./range.js&#39;).range(ev.clientX - disX + disW , 500 , 100);
        var H = require(&#39;./range.js&#39;).range(ev.clientY - disY + disH , 500 , 100);
         
        obj1.style.width = W + &#39;px&#39;;
        obj1.style.height = H + &#39;px&#39;;
      };
      document.onmouseup = function(){
        document.onmousemove = null;
        document.onmouseup = null;
      };
      return false;
    };
     
  }
   
  exports.scale = scale;
   
});
ログイン後にコピー

D同事

// D同事的range.js--限定拖拽范围
 
  define(function(require,exports,module){
     
    function range(iNum,iMax,iMin){
       
      if( iNum > iMax ){
        return iMax;
      }
      else if( iNum < iMin ){
        return iMin;
      }
      else{
        return iNum;
      }
       
    }
     
    exports.range = range;
     
  });
ログイン後にコピー

requirejs开发实例

require.config是用来定义别名的,在paths属性下配置别名。然后通过requirejs(参数一,参数二);参数一是数组,传入我们需要引用的模块名,第二个参数是个回调函数,回调函数传入一个变量,代替刚才所引入的模块。

main.js文件

//别名配置
requirejs.config({
  paths: {
    jquery: &#39;jquery.min&#39; //可以省略.js
  }
});
//引入模块,用变量$表示jquery模块
requirejs([&#39;jquery&#39;], function ($) {
  $(&#39;body&#39;).css(&#39;background-color&#39;,&#39;red&#39;);
});
ログイン後にコピー

引入模块也可以只写require()。requirejs通过define()定义模块,定义的参数上同。在此模块内的方法和变量外部是无法访问的,只有通过return返回才行.

define 模块

define([&#39;jquery&#39;], function ($) {//引入jQuery模块
  return {
    add: function(x,y){
      return x + y;
    }
  };
});
ログイン後にコピー

将该模块命名为math.js保存。

main.js引入模块方法

require([&#39;jquery&#39;,&#39;math&#39;], function ($,math) {
  console.log(math.add(10,100));//110
});
ログイン後にコピー

没有依赖

如果定义的模块不依赖其他模块,则可以:

define(function () {
 
  return {
    name: "trigkit4",
    age: "21"
  }
});
ログイン後にコピー

   

AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exports或exports的属性赋值来达到暴露模块对象的目的。

更多JavaScript 中对象的深拷贝相关文章请关注PHP中文网!

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

モジュール開発に PHP と webpack を使用する方法 モジュール開発に PHP と webpack を使用する方法 May 11, 2023 pm 03:52 PM

Web 開発テクノロジーの継続的な発展に伴い、フロントエンドとバックエンドの分離とモジュール開発が広く普及する傾向になりました。 PHP は一般的に使用されるバックエンド言語です。モジュラー開発を行う場合、モジュールの管理とパッケージ化にいくつかのツールを使用する必要があります。Webpack は非常に使いやすいモジュラー パッケージング ツールです。この記事では、モジュール開発に PHP と webpack を使用する方法を紹介します。 1. モジュラー開発とは何ですか? モジュラー開発とは、プログラムを、それぞれが独自の機能を持つ独立したモジュールに分解することを指します。

PHP 学習ノート: モジュール開発とコードの再利用 PHP 学習ノート: モジュール開発とコードの再利用 Oct 10, 2023 pm 12:58 PM

PHP 学習メモ: モジュール開発とコードの再利用 はじめに: ソフトウェア開発において、モジュール開発とコードの再利用は非常に重要な概念です。モジュール開発では、複雑なシステムを管理しやすい小さなモジュールに分解して、開発効率とコードの保守性を向上させることができ、コードの再利用により、冗長なコードを削減し、コードの再利用性を向上させることができます。 PHP 開発では、何らかの技術的手段を通じてモジュール開発とコードの再利用を実現できます。この記事では、読者がこれらの概念をより深く理解し、適用できるように、一般的に使用されるいくつかのテクノロジと具体的なコード例を紹介します。

C++ 開発のアドバイス: モジュール式 C++ 開発の実行方法 C++ 開発のアドバイス: モジュール式 C++ 開発の実行方法 Nov 23, 2023 am 08:56 AM

C++ 言語は、汎用の高級プログラミング言語として、さまざまなアプリケーションやシステムの開発に広く使用されています。ただし、C++ の複雑さと柔軟性により、特に大規模なプロジェクトでは、開発者はいくつかの課題に直面することになります。大規模なプロジェクトに取り組む場合、モジュール型の開発アプローチが重要です。この記事では、モジュール式 C++ 開発を行う方法を紹介し、いくつかの提案とベスト プラクティスを提供します。モジュール開発とは、大規模なプロジェクトを複数の小さなモジュールに分割することを指します。各モジュールには独自の機能と責任があり、モジュール間のインターフェイスを通じて通信します。

ThinkPHP6 モジュール開発: アプリケーション ロジックの解体 ThinkPHP6 モジュール開発: アプリケーション ロジックの解体 Aug 12, 2023 am 10:53 AM

ThinkPHP6 モジュール開発: アプリケーション ロジックの解体 インターネットの急速な発展に伴い、Web アプリケーション開発はますます複雑になってきました。大規模なアプリケーションには複数のモジュールが含まれる場合があり、各モジュールは異なる機能を担当し、アプリケーション ロジックの逆アセンブルは考慮する必要がある問題になります。この記事では、ThinkPHP6 でモジュール開発を実装する方法を紹介し、読者の理解を助けるコード例を使用します。 1. モジュールの作成 ThinkPHP6 では、モジュールはアプリケーションの機能を分割したもので、実際のニーズに応じてさまざまなモジュールを作成できます。

Linux システムで Python スクリプトのモジュール開発を実装するための技術ガイド Linux システムで Python スクリプトのモジュール開発を実装するための技術ガイド Oct 05, 2023 am 11:53 AM

Linux システムで Python スクリプトのモジュール開発を実装するためのテクニカル ガイド はじめに: Python は、さまざまな分野の開発で広く使用されている、学びやすく強力な高レベル プログラミング言語です。 Linux システムでは、Python スクリプトのモジュール開発により、コードの保守性と再利用性が効果的に向上し、開発と保守のコストが削減されます。この記事では、Python を使用して Linux システムでモジュラー開発を実装する方法に関する技術ガイドラインを紹介し、具体的なコード例を示します。 1. モジュール化

Vue 開発の提案: モジュール開発とコンポーネントの再利用を実行する方法 Vue 開発の提案: モジュール開発とコンポーネントの再利用を実行する方法 Nov 22, 2023 am 09:51 AM

Vue は、ユーザー インターフェイスを構築するための人気のある JavaScript フレームワークです。コンポーネントベースの開発アプローチを採用しており、開発者はモジュール開発とコンポーネントの再利用を簡単に実行できます。この記事では、モジュール開発とコンポーネントの再利用を実装する方法に関する Vue 開発の提案をいくつか紹介します。 1. モジュール開発 モジュール開発は、複雑なシステムをいくつかの独立したモジュールに分解する方法であり、各モジュールは特定の機能を完了する役割を果たします。 Vue では、Vue コンポーネントを使用してモジュール開発を実現できます。モジュールに関する情報は次のとおりです

マイクロサービス アーキテクチャで PHP 関数のモジュール開発を実装するにはどうすればよいですか? マイクロサービス アーキテクチャで PHP 関数のモジュール開発を実装するにはどうすればよいですか? Sep 18, 2023 pm 01:31 PM

マイクロサービス アーキテクチャで PHP 関数のモジュール開発を実装するにはどうすればよいですか?テクノロジーが進化し続けるにつれて、ソフトウェア開発ではマイクロサービス アーキテクチャの人気が高まっています。大規模なアプリケーションを多数の小さな独立した機能モジュールに分割し、それぞれを独立して開発、展開、拡張できます。 PHP 開発者にとって、マイクロサービス アーキテクチャを使用して機能のモジュール開発を実現する方法は重要なトピックです。この記事では、マイクロサービス アーキテクチャの下で PHP 機能のモジュール開発を実現するためのいくつかのテクノロジとベスト プラクティスを紹介します。初め

Spring Boot のモジュール開発とアプリケーションのシナリオ Spring Boot のモジュール開発とアプリケーションのシナリオ Jun 23, 2023 am 09:16 AM

SpringBoot について話すとき、私たちは通常、高速開発フレームワークを思い浮かべます。ただし、そのメリットはそれだけではありません。 SpringBoot のもう 1 つの優れた特徴は、モジュール型開発をサポートしていることです。これにより、開発が容易になり、保守が容易になります。この記事では、SpringBoot モジュール開発の基本と、この機能を実際のアプリケーションで使用する方法について説明します。 SpringBootモジュールとは何ですか? SpringBoot モジュールは一連の機能です

See all articles