JavaScript로 네임 스페이스를 작성하여 객체와 함수를 다른 이름의 객체와 함수로 덮어 쓰지 않도록하려면 어떻게해야합니까? 나는 다음을 사용했다 :
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
이것을하는 더 우아하거나 간결한 방법이 있습니까?
JavaScript로 네임 스페이스를 작성하여 객체와 함수를 다른 이름의 객체와 함수로 덮어 쓰지 않도록하려면 어떻게해야합니까? 나는 다음을 사용했다 :
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
이것을하는 더 우아하거나 간결한 방법이 있습니까?
답변:
나는 이것을 좋아한다 :
var yourNamespace = {
foo: function() {
},
bar: function() {
}
};
...
yourNamespace.foo();
MyApp
, 예를 들면 MyApp.Views.Profile = {}
보다는 MyApp.users = {}
하고 MyViews.Profile = {}
. 반드시 2 단계의 깊이 만 있어야하는 것은 아닙니다.
Enterprise jQuery 사이트에서 찾은 접근 방식을 사용 합니다 .
다음은 개인 및 공용 속성 및 함수를 선언하는 방법을 보여주는 예입니다. 모든 것은 자체 실행 익명 기능으로 수행됩니다.
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.ingredient = "Bacon Strips";
//Public Method
skillet.fry = function() {
var oliveOil;
addItem( "\t\n Butter \n\t" );
addItem( oliveOil );
console.log( "Frying " + skillet.ingredient );
};
//Private Method
function addItem( item ) {
if ( item !== undefined ) {
console.log( "Adding " + $.trim(item) );
}
}
}( window.skillet = window.skillet || {}, jQuery ));
따라서 공개 멤버 중 하나에 액세스하려면 skillet.fry()
또는을 방문하십시오 skillet.ingredients
.
정말 멋진 점은 이제 동일한 구문을 사용하여 네임 스페이스를 확장 할 수 있다는 것입니다.
//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
//Private Property
var amountOfGrease = "1 Cup";
//Public Method
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
console.log( isHot ? "Hot" : "Cold" );
};
}( window.skillet = window.skillet || {}, jQuery ));
undefined
논쟁세 번째
undefined
인수는 value 변수의 소스입니다undefined
. 그것이 오늘날에도 여전히 관련이 있는지 확실하지 않지만 구형 브라우저 / JavaScript 표준 (ecmascript 5, javascript <1.8.5 ~ firefox 4)으로 작업하는 동안 전역 범위 변수undefined
를 쓸 수 있으므로 누구나 그 가치를 다시 쓸 수 있습니다. 세 번째 인수 (값을 전달하지 않은 경우)undefined
는 네임 스페이스 / 함수로 범위가 지정된 변수를 만듭니다 . 네임 스페이스를 작성할 때 값이 전달되지 않았으므로 기본값은 valueundefined
입니다.
undefined
인수는 value 변수의 소스입니다 undefined
. 구형 브라우저 / 자바 스크립트 표준 (ecmascript 5, javascript <1.8.5 ~ firefox 4)으로 작업하는 동안 전역 범위 변수 undefined
를 쓸 수 있으므로 누구나 해당 값을 다시 쓸 수 있습니다. 세 번째로 전달하지 않는 추가 인수를 추가하면 value undefined
가되므로 undefined
외부 소스에서 다시 작성하지 않는 네임 스페이스 범위 를 작성했습니다.
window.skillet = window.skillet || {}
은 실행 순서를 미리 모르는 경우 여러 스크립트가 동일한 네임 스페이스에 안전하게 추가 할 수 있다는 것입니다. 코드를 손상시키지 않고 스크립트 포함을 임의로 재정렬하려는 경우 또는 async 속성을 사용 하여 스크립트를 비동기식으로로드 하여 실행 순서를 보장하지 않는 경우 유용합니다 . 참조 stackoverflow.com/questions/6439579/...
객체 리터럴 형식보다 조금 덜 제한적이라고 생각하는 또 다른 방법은 다음과 같습니다.
var ns = new function() {
var internalFunction = function() {
};
this.publicFunction = function() {
};
};
위의 내용은 모듈 패턴 과 비슷 하며 , 원하는지 여부에 관계없이 객체 리터럴의 엄격한 구조를 피하면서 모든 기능을 공개로 노출 할 수 있습니다.
ns().publicFunction()
즉, ns.publicFunction()
작동합니다.
new
키워드 앞에 function
키워드가 필요하기 때문입니다. 기본적으로 수행중인 작업은 익명 함수를 선언하고 (함수는 생성자이기도 함) 즉시를 사용하여 생성자로 호출한다는 것 new
입니다. 따라서 내부 ns
에 저장되는 최종 값 은 해당 익명 생성자의 (고유 한) 인스턴스입니다. 이해가 되길 바랍니다.
이것을하는 더 우아하거나 간결한 방법이 있습니까?
예. 예를 들면 다음과 같습니다.
var your_namespace = your_namespace || {};
그럼 당신은 가질 수 있습니다
var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:'test'};
your_namespace.Bar = function(arg)
{
alert(arg);
};
with(your_namespace)
{
Bar(Foo.toAlert);
}
var your_namespace = your_namespace = your_namespace || {}
나는 일반적으로 클로저로 빌드합니다.
var MYNS = MYNS || {};
MYNS.subns = (function() {
function privateMethod() {
// Do private stuff, or build internal.
return "Message";
}
return {
someProperty: 'prop value',
publicMethod: function() {
return privateMethod() + " stuff";
}
};
})();
몇 년 동안 내 스타일은이 글을 쓴 후 미묘한 변화를 겪었으며 이제는 다음과 같이 클로저를 작성하는 것으로 나타났습니다.
var MYNS = MYNS || {};
MYNS.subns = (function() {
var internalState = "Message";
var privateMethod = function() {
// Do private stuff, or build internal.
return internalState;
};
var publicMethod = function() {
return privateMethod() + " stuff";
};
return {
someProperty: 'prop value',
publicMethod: publicMethod
};
})();
이런 식으로 공개 API와 구현을 이해하기가 더 쉽다는 것을 알게되었습니다. return 문은 구현에 대한 공용 인터페이스라고 생각하십시오.
MYNS.subns = MYNS.subns || {}
??
var foo = function
및 function foo
개인되고, 유사하다; JavaScript의 동적 형식 특성으로 인해 대부분의 인터프리터 파이프 라인에서 몇 가지 명령을 건너 뛰기 때문에 후자가 약간 더 빠릅니다. 를 사용 var foo
하면 유형 시스템이 해당 var에 지정된 유형을 찾기 위해 호출되어야하지만 function foo
유형 시스템은 자동으로 함수임을 알고 있으므로 몇 가지 함수 호출을 건너 뛰므로 CPU 명령 호출이 줄어 듭니다. jmp
, pushq
, popq
, 등, 짧은 CPU 파이프 라인으로 변환한다.
function foo
문법이 더 읽기 쉽다고 주장한다 . 그리고 나는 여전히 내 버전을 좋아합니다.
다른 JavaScript 파일을 작성하여 나중에 응용 프로그램에서 결합하거나 결합하지 않을 수 있으므로 각 파일은 다른 파일의 작업을 손상시키지 않으면 서 네임 스페이스 객체를 복구하거나 구성 할 수 있어야합니다.
하나의 파일이 네임 스페이스를 사용하려고 할 수 있습니다 namespace.namespace1
.
namespace = window.namespace || {};
namespace.namespace1 = namespace.namespace1 || {};
namespace.namespace1.doSomeThing = function(){}
다른 파일은 네임 스페이스를 사용하려고 할 수 있습니다 namespace.namespace2
.
namespace = window.namespace || {};
namespace.namespace2 = namespace.namespace2 || {};
namespace.namespace2.doSomeThing = function(){}
이 두 파일은 충돌하지 않고 함께 또는 떨어져있을 수 있습니다.
다음은 Stoyan Stefanov가 JavaScript 패턴 책 에서 어떻게 수행했는지 잘 보여줍니다. (자동 생성 된 API 문서를 허용하는 주석과 사용자 정의 객체의 프로토 타입에 메소드를 추가하는 방법도 보여줍니다) :
/**
* My JavaScript application
*
* @module myapp
*/
/** @namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};
/**
* A maths utility
* @namespace MYAPP
* @class math_stuff
*/
MYAPP.math_stuff = {
/**
* Sums two numbers
*
* @method sum
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} Sum of the inputs
*/
sum: function (a, b) {
return a + b;
},
/**
* Multiplies two numbers
*
* @method multi
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} The inputs multiplied
*/
multi: function (a, b) {
return a * b;
}
};
/**
* Constructs Person objects
* @class Person
* @constructor
* @namespace MYAPP
* @param {String} First name
* @param {String} Last name
*/
MYAPP.Person = function (first, last) {
/**
* First name of the Person
* @property first_name
* @type String
*/
this.first_name = first;
/**
* Last name of the Person
* @property last_name
* @type String
*/
this.last_name = last;
};
/**
* Return Person's full name
*
* @method getName
* @return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
return this.first_name + ' ' + this.last_name;
};
나는이 접근법을 사용한다 :
var myNamespace = {}
myNamespace._construct = function()
{
var staticVariable = "This is available to all functions created here"
function MyClass()
{
// Depending on the class, we may build all the classes here
this.publicMethod = function()
{
//Do stuff
}
}
// Alternatively, we may use a prototype.
MyClass.prototype.altPublicMethod = function()
{
//Do stuff
}
function privateStuff()
{
}
function publicStuff()
{
// Code that may call other public and private functions
}
// List of things to place publically
this.publicStuff = publicStuff
this.MyClass = MyClass
}
myNamespace._construct()
// The following may or may not be in another file
myNamespace.subName = {}
myNamespace.subName._construct = function()
{
// Build namespace
}
myNamespace.subName._construct()
외부 코드는 다음과 같습니다.
var myClass = new myNamespace.MyClass();
var myOtherClass = new myNamepace.subName.SomeOtherClass();
myNamespace.subName.publicOtherStuff(someParameter);
ns = ns || {}
힘은 다른 예기치 않은 결과가 발생할 수 있습니다 더 방어 보인다.
다음은 userspace826의 Namespace.js 링크에 대한 후속 조치입니다. 프로젝트가 GitHub 로 옮겨 간 것 같습니다 . 이제 smith / namespacedotjs 입니다.
나는 작은 프로젝트 에이 간단한 JavaScript 도우미를 사용해 왔으며 지금까지 네임 스페이스 및 로드 모듈 / 클래스 를 처리 할 수있을만큼 가볍고 다재다능 합니다. 전역 네임 스페이스뿐만 아니라 한숨을 내쉬고 선택한 네임 스페이스로 패키지를 가져올 수 있다면 좋을 것입니다. 그러나 그것은 요점입니다.
네임 스페이스를 선언 한 다음 해당 네임 스페이스에서 객체 / 모듈을 정의 할 수 있습니다.
Namespace('my.awesome.package');
my.awesome.package.WildClass = {};
또 다른 옵션은 네임 스페이스와 해당 내용을 한 번에 선언하는 것입니다.
Namespace('my.awesome.package', {
SuperDuperClass: {
saveTheDay: function() {
alert('You are welcome.');
}
}
});
더 많은 사용법 예제 는 source 에서 example.js 파일을보십시오 .
견본:
var namespace = {};
namespace.module1 = (function(){
var self = {};
self.initialized = false;
self.init = function(){
setTimeout(self.onTimeout, 1000)
};
self.onTimeout = function(){
alert('onTimeout')
self.initialized = true;
};
self.init(); /* If it needs to auto-initialize, */
/* You can also call 'namespace.module1.init();' from outside the module. */
return self;
})()
당신은 선택적으로 선언 할 수 있습니다 local
, 변수를 same
같이 self
하고 지정 local.onTimeout
이 비공개로합니다.
네임 스페이스를 제공하는 간단한 함수를 선언 할 수 있습니다.
function namespace(namespace) {
var object = this, tokens = namespace.split("."), token;
while (tokens.length > 0) {
token = tokens.shift();
if (typeof object[token] === "undefined") {
object[token] = {};
}
object = object[token];
}
return object;
}
// Usage example
namespace("foo.bar").baz = "I'm a value!";
개인 범위가 필요한 경우 :
var yourNamespace = (function() {
//Private property
var publicScope = {};
//Private property
var privateProperty = "aaa";
//Public property
publicScope.publicProperty = "bbb";
//Public method
publicScope.publicMethod = function() {
this.privateMethod();
};
//Private method
function privateMethod() {
console.log(this.privateProperty);
}
//Return only the public parts
return publicScope;
}());
yourNamespace.publicMethod();
개인 범위를 사용하지 않는 경우 :
var yourNamespace = {};
yourNamespace.publicMethod = function() {
// Do something...
};
yourNamespace.publicMethod2 = function() {
// Do something...
};
yourNamespace.publicMethod();
모듈 패턴은 원래 기존 소프트웨어 엔지니어링의 클래스에 개인 및 공개 캡슐화를 모두 제공하는 방법으로 정의되었습니다.
모듈 패턴으로 작업 할 때 시작하기 위해 사용하는 간단한 템플릿을 정의하는 것이 유용 할 수 있습니다. 이름 간격, 공용 및 개인 변수를 다루는 것이 있습니다.
JavaScript에서 모듈 패턴은 단일 객체 내에 공개 / 비공개 메소드와 변수를 모두 포함 할 수있는 방식으로 클래스 개념을 추가로 에뮬레이트하는 데 사용되므로 특정 부분을 전역 범위로부터 보호합니다. 결과적으로 함수 이름이 페이지의 추가 스크립트에 정의 된 다른 함수와 충돌 할 가능성이 줄어 듭니다.
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
// A private counter variable
myPrivateVar = 0;
// A private function which logs any arguments
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
// A public variable
myPublicVar: "foo",
// A public function utilizing privates
myPublicFunction: function( bar ) {
// Increment our private counter
myPrivateVar++;
// Call our private method using bar
myPrivateMethod( bar );
}
};
})();
장점
왜 모듈 패턴이 좋은 선택입니까? 초보자에게는 적어도 JavaScript 관점에서 진정한 캡슐화 아이디어보다 객체 지향적 배경에서 개발자가 훨씬 더 깨끗합니다.
둘째, 개인 데이터를 지원하므로 모듈 패턴에서 코드의 공개 부분은 개인 부분을 만질 수 있지만 외부 세계는 클래스의 개인 부분을 만질 수 없습니다.
단점
모듈 패턴의 단점은 공개 멤버와 개인 멤버 모두에 다르게 액세스하므로 가시성을 변경하려면 실제로 멤버가 사용 된 각 위치를 변경해야한다는 것입니다.
또한 나중에 개체에 추가 된 메서드에서 개인 멤버에 액세스 할 수 없습니다 . 즉, 많은 경우에 모듈 패턴은 여전히 매우 유용하며 올바르게 사용되면 응용 프로그램의 구조를 개선 할 수있는 가능성이 있습니다.
공개 모듈 패턴
이제 우리는 모듈 패턴에 좀 더 익숙해 졌으므로 약간 개선 된 버전 인 Christian Heilmann의 Revealing Module 패턴을 살펴 보겠습니다.
공개 모듈 패턴은 Heilmann이 우리가 하나의 공용 메소드를 다른 메소드에서 호출하거나 공용 변수에 액세스하려고 할 때 주 객체의 이름을 반복해야한다는 사실에 좌절하면서 생겨났습니다. 그가 공개하고자하는 것들에 대한 문자 표기법에 반대하는 것.
그의 노력의 결과는 개인 범위에서 모든 함수와 변수를 간단하게 정의하고 공개로 공개하려는 개인 기능에 대한 포인터와 함께 익명 객체를 반환하는 업데이트 된 패턴이었습니다.
공개 모듈 패턴을 사용하는 방법의 예는 아래에 있습니다.
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
장점
이 패턴을 사용하면 스크립트 구문이보다 일관되게됩니다. 또한 모듈의 끝에서 우리의 기능과 변수 중 어느 것이 공개적으로 액세스 될 수 있는지 더 명확하게하여 가독성을 쉽게합니다.
단점
이 패턴의 단점은 개인 기능이 공용 기능을 참조하는 경우 패치가 필요한 경우 해당 공용 기능을 대체 할 수 없다는 것입니다. 개인 함수는 계속 개인 구현을 참조하고 패턴은 공용 멤버에게 적용되지 않고 함수에만 적용되기 때문입니다.
개인 변수를 참조하는 공용 객체 멤버에도 위의 패치 없음 규칙이 적용됩니다.
Erlang의 모듈에서 영감을 얻은 네임 스페이스 를 만들었습니다 . 매우 기능적인 접근 방식이지만 요즘 JavaScript 코드를 작성하는 방법입니다.
클로저에 전역 네임 스페이스를 제공하고 해당 클로저 내에 정의 된 집합 함수를 노출합니다.
(function(){
namespace("images", previous, next);
// ^^ This creates or finds a root object, images, and binds the two functions to it.
// It works even though those functions are not yet defined.
function previous(){ ... }
function next(){ ... }
function find(){ ... } // A private function
})();
여러 라이브러리를 다른 프로젝트로 이식하고 최상위 (정적으로 이름이 지정된) 네임 스페이스를 지속적으로 변경 한 후 네임 스페이스를 정의하기 위해이 작은 (오픈 소스) 도우미 함수를 사용하도록 전환했습니다.
global_namespace.Define('startpad.base', function(ns) {
var Other = ns.Import('startpad.other');
....
});
이점에 대한 설명은 내 블로그 게시물에 있습니다. 여기 에서 소스 코드를 얻을 수 있습니다 .
내가 정말로 좋아하는 이점 중 하나는로드 순서와 관련하여 모듈 간 격리입니다. 외부 모듈을로드하기 전에 참조 할 수 있습니다. 코드를 사용할 수있을 때 얻을 수있는 객체 참조가 채워집니다.
네임 스페이스에 다음 구문을 사용합니다.
var MYNamespace = MYNamespace|| {};
MYNamespace.MyFirstClass = function (val) {
this.value = val;
this.getValue = function(){
return this.value;
};
}
var myFirstInstance = new MYNamespace.MyFirstClass(46);
alert(myFirstInstance.getValue());
jsfiddle : http://jsfiddle.net/rpaul/4dngxwb3/1/
나는 파티에 7 년 늦었지만이 8 년 전에는 많은 일을했다.
JavaScript 전역 네임 스페이스를 유지하면서 (네임 스페이스 오염 방지) 네임 스페이스 경로의 기존 객체를 방해하지 않으면 서 복잡한 웹 애플리케이션을 구성하고 관리하기 쉽게 중첩 된 여러 네임 스페이스를 쉽고 효율적으로 작성할 수 있어야합니다. .
위의 2008 년 1 월 솔루션입니다.
var namespace = function(name, separator, container){
var ns = name.split(separator || '.'),
o = container || window,
i,
len;
for(i = 0, len = ns.length; i < len; i++){
o = o[ns[i]] = o[ns[i]] || {};
}
return o;
};
이것은 네임 스페이스를 생성하는 것이 아니라 네임 스페이스를 생성하는 기능을 제공합니다.
이것은 축소 된 하나의 라이너로 요약 될 수 있습니다.
var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g};
사용 예 :
namespace("com.example.namespace");
com.example.namespace.test = function(){
alert("In namespaced function.");
};
또는 하나의 진술로 :
namespace("com.example.namespace").test = function(){
alert("In namespaced function.");
};
그런 다음 다음과 같이 실행됩니다.
com.example.namespace.test();
레거시 브라우저에 대한 지원이 필요하지 않은 경우 업데이트 된 버전 :
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || '.').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
이제 namespace
전역 네임 스페이스 자체 에 노출 되는 것에 대해 리리가 될 것입니다. (기본 언어가 우리에게 이것을 제공하지 못하는 것은 너무 나쁩니다!) 따라서 나는 일반적으로 다음과 같은 클로저에서 이것을 직접 사용합니다.
(function(){
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || '.').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
const ns = namespace("com.ziesemer.myApp");
// Optional:
ns.namespace = ns;
// Further extend, work with ns from here...
}());
console.log("\"com\":", com);
더 큰 응용 프로그램에서는 페이지로드 시작시 클라이언트 클라이언트 웹 응용 프로그램의 경우 한 번만 정의하면됩니다. 그런 다음 추가 파일이 유지되면 네임 스페이스 함수를 재사용 할 수 있습니다 (위의 "선택 사항"으로 포함). 최악의 경우,이 함수가 몇 번 다시 선언되면 코드는 몇 줄에 불과하고 축소 된 경우에는 줄어 듭니다.
내가 가장 좋아하는 패턴은 최근에 이렇게되었다 :
var namespace = (function() {
// expose to public
return {
a: internalA,
c: internalC
}
// all private
/**
* Full JSDoc
*/
function internalA() {
// ...
}
/**
* Full JSDoc
*/
function internalB() {
// ...
}
/**
* Full JSDoc
*/
function internalC() {
// ...
}
/**
* Full JSDoc
*/
function internalD() {
// ...
}
})();
물론 반환은 끝날 수 있지만 함수 선언 만 뒤에 오는 경우 네임 스페이스가 무엇인지, 어떤 API가 노출되는지 훨씬 쉽게 알 수 있습니다.
이러한 경우 함수 표현식을 사용하는 패턴은 전체 코드를 거치지 않고 어떤 메소드가 노출되는지 알 수 없습니다.
namespace.a();
그런 간단한 문제에 대해 너무 많은 코드를 사용한다고 생각합니다. 그에 대한 저장소를 만들 필요가 없습니다. 한 줄 기능이 있습니다.
namespace => namespace.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window);
시도 해봐 :
// --- definition ---
const namespace = namespace => namespace.split(".").reduce((last, next) => (last[next] = (last[next] || {})), window);
// --- Use ----
let myNamespace = namespace("a.b.c");
myNamespace.MyClass = class MyClass {};
// --- see ----
console.log("a : ", a);
Makefile을 사용하는 경우이 작업을 수행 할 수 있습니다.
// prelude.hjs
billy = new (
function moduleWrapper () {
const exports = this;
// postlude.hjs
return exports;
})();
// someinternalfile.js
function bob () { console.log('hi'); }
exports.bob = bob;
// clientfile.js
billy.bob();
약 1000 줄에 도달하면 Makefile을 사용하는 것이 좋습니다 .makefile에서 한 줄을 제거하여 큰 코드를 효과적으로 주석 처리 할 수 있기 때문입니다. 물건과 함께 쉽게 바이올린을 만들 수 있습니다. 또한이 기술을 사용하면 네임 스페이스가 서곡에 한 번만 나타나므로 변경하기 쉽고 라이브러리 코드 내에서 계속 반복 할 필요가 없습니다.
makefile을 사용할 때 브라우저에서 라이브 개발을위한 쉘 스크립트 :
while (true); do make; sleep 1; done
이것을 make 작업으로 'go'로 추가하면 코딩 할 때 빌드를 최신 상태로 유지하기 위해 'make go'할 수 있습니다.
Ionuț G. Stan의 답변에 대한 후속 조치이지만 var ClassFirst = this.ClassFirst = function() {...}
동일한 네임 스페이스의 클래스에 대한 네임 스페이스 혼란을 줄이기 위해 JavaScript의 폐쇄 범위를 사용하는을 사용하여 깔끔한 코드의 이점을 보여줍니다 .
var Namespace = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 123;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
var Namespace2 = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 666;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace2.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
new Namespace.ClassSecond()
new Namespace2.ClassSecond()
산출:
Cluttered way to access another class in namespace: 123
Nicer way to access a class in same namespace: 123
Cluttered way to access another class in namespace: 666
Nicer way to access a class in same namespace: 666
패키지 / 단위가 다른 언어로 작동하는 것과 약간 비슷한 다른 네임 스페이스 라이브러리를 작성했습니다. JavaScript 코드 패키지와 다른 코드에서 해당 패키지 참조를 작성할 수 있습니다.
Package("hello", [], function() {
function greeting() {
alert("Hello World!");
}
// Expose function greeting to other packages
Export("greeting", greeting);
});
Package("example", ["hello"], function(greeting) {
// Greeting is available here
greeting(); // Alerts: "Hello World!"
});
두 번째 파일 만 페이지에 포함하면됩니다. 의존성 (파일 hello.js 이 예제에서는 )이 자동으로로드되고 해당 종속성에서 내 보낸 객체가 콜백 함수의 인수를 채우는 데 사용됩니다.
Packages JS 에서 관련 프로젝트를 찾을 수 있습니다 .
내 습관은 myName () 함수 를 속성 저장소로 사용하고 var myName 을 "method"홀더로 사용하는 것입니다.
이것이 합법적이든 아니든, 나를 이길! 나는 항상 내 PHP 논리에 의존하고 있으며 일이 간단합니다. :디
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(myObj instanceof Function !== false)
? Object.create({
$props: new myObj(),
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
: console.log('Object creation failed!')
);
if (this !== that) myObj.fName1(); else myObj.fName2();
당신은 또한 객체 생성하기 전에 확인하는 '반대'방법으로 그것을 할 수있는 훨씬 더 :
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(typeof(myObj) !== "function" || myObj instanceof Function === false)
? new Boolean()
: Object.create({
$props: new myObj(),
init: function () { return; },
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
);
if (myObj instanceof Boolean) {
Object.freeze(myObj);
console.log('myObj failed!');
debugger;
}
else
myObj.init();
이것에 대한 참조 : JavaScript : Object.create ()로 객체 만들기
JavaScript에는 네임 스페이스를 사용하기위한 미리 정의 된 방법이 없습니다. JavaScript에서는 네임 스페이스를 정의하기위한 고유 한 메서드를 만들어야합니다. 다음은 Oodles 기술에서 수행하는 절차입니다.
네임 스페이스 등록 다음은 네임 스페이스를 등록하는 기능입니다.
//Register NameSpaces Function
function registerNS(args){
var nameSpaceParts = args.split(".");
var root = window;
for(var i=0; i < nameSpaceParts.length; i++)
{
if(typeof root[nameSpaceParts[i]] == "undefined")
root[nameSpaceParts[i]] = new Object();
root = root[nameSpaceParts[i]];
}
}
네임 스페이스를 등록하려면 이름 공간으로 인수를 '.'
점으로 구분하여 위 함수를 호출하십시오 . 예를 들어 응용 프로그램 이름은 oodle입니다. 다음 방법으로 네임 스페이스를 만들 수 있습니다.
registerNS("oodles.HomeUtilities");
registerNS("oodles.GlobalUtilities");
var $OHU = oodles.HomeUtilities;
var $OGU = oodles.GlobalUtilities;
기본적으로 백엔드에서 아래와 같이 네임 스페이스 구조를 만듭니다.
var oodles = {
"HomeUtilities": {},
"GlobalUtilities": {}
};
위 함수에서 "oodles.HomeUtilities"
and 라는 네임 스페이스를 등록했습니다 "oodles.GlobalUtilities"
. 이러한 네임 스페이스를 호출하기 위해 변수 var $OHU
및 var를 $OGU
만듭니다.
이러한 변수는 네임 스페이스 초기화와 별개 일뿐입니다. 이제, 속한 함수를 선언 할 때마다 HomeUtilities
다음과 같이 선언합니다.
$OHU.initialization = function(){
//Your Code Here
};
위의 함수 이름 초기화는 네임 스페이스에 저장 $OHU
됩니다. 스크립트 파일의 어느 곳에서나이 함수를 호출합니다. 다음 코드를 사용하십시오.
$OHU.initialization();
마찬가지로 다른 네임 스페이스도 마찬가지입니다.
도움이 되길 바랍니다.
JavaScript는 기본적으로 네임 스페이스를 지원하지 않습니다. 따라서 요소 (함수, 메소드, 객체, 변수)를 만들면 전역이되고 전역 네임 스페이스를 오염시킵니다. 네임 스페이스없이 두 함수를 정의하는 예제를 보자.
function func1() {
console.log("This is a first definition");
}
function func1() {
console.log("This is a second definition");
}
func1(); // This is a second definition
항상 두 번째 함수 정의를 호출합니다. 이 경우 네임 스페이스는 이름 충돌 문제를 해결합니다.