JavaScript 날짜 Object.freeze () 방법이 있습니까?
MDN Object.freeze()
문서 에 따르면 :
이
Object.freeze()
메서드는 개체를 고정합니다. 즉, 새 속성이 추가되지 않도록합니다. 기존 속성이 제거되는 것을 방지합니다. 기존 속성 또는 열거 가능성, 구성 가능성 또는 쓰기 가능성이 변경되는 것을 방지합니다. 본질적으로 객체는 사실상 불변으로 만들어집니다. 이 메서드는 고정중인 개체를 반환합니다.
날짜에 고정을 호출하면 해당 날짜가 변경되지 않을 것으로 예상했지만 작동하지 않는 것 같습니다. 내가하는 일은 다음과 같다 (Node.js v5.3.0 실행).
let d = new Date()
Object.freeze(d)
d.setTime(0)
console.log(d) // Wed Dec 31 1969 16:00:00 GMT-0800 (PST)
나는 호출이 setTime
실패하거나 아무것도하지 않을 것이라고 예상했을 것이다 . 데이트를 동결하는 방법에 대한 아이디어가 있습니까?
JavaScript 날짜 Object.freeze () 방법이 있습니까?
나는 그렇게 생각하지 않는다. 하지만 가까이 다가 갈 수 있습니다 . 아래 줄을 참조하십시오. 하지만 먼저 Object.freeze
작동하지 않는 이유를 살펴 보겠습니다 .
날짜에 고정을 호출하면 해당 날짜가 변경되지 않을 것으로 예상했습니다.
그것은 할 경우 Date
내부 시간 값을 유지하기 위해 객체 속성을 사용하지만, 그렇지 않습니다. 그것은 사용하는 [[DateValue]]
내부 슬롯 대신. 내부 슬롯 은 속성이 아닙니다.
내부 슬롯은 객체와 연결되고 다양한 ECMAScript 사양 알고리즘에서 사용되는 내부 상태에 해당합니다. 내부 슬롯은 개체 속성이 아닙니다 ...
따라서 오브젝트를 고정해도 [[DateValue]]
내부 슬롯 을 변경하는 기능에는 영향을주지 않습니다 .
를 고정 Date
하거나 효과적으로 고정 할 수 있습니다 . 모든 mutator 메서드를 no-op 함수 (또는 오류를 발생시키는 함수)로 바꾼 다음 freeze
이를 대체 합니다. 그러나 zzzzBov (좋은 것!)에 의해 관찰 되었 듯이 , 이것은 누군가가 (고정 된 객체를 우회하려는 의도적으로 시도하거나 그들이 사용하는 복잡한 코드의 부산물로)하는 것을 방해하지 않습니다 . 그래서 가깝지만 시가는 없습니다.Date.prototype.setTime.call(d, 0)
다음은 예입니다 ( let
코드에서 확인 했으므로 여기에서는 ES2015 기능을 사용 하고 있으므로이를 실행하려면 최신 브라우저가 필요하지만 ES5 전용 기능으로도 수행 할 수 있습니다) :
"use strict";
let d = new Date();
freezeDate(d);
d.setTime(0);
snippet.log(d);
function nop() {
}
function freezeDate(d) {
allNames(d).forEach(name => {
if (name.startsWith("set") && typeof d[name] === "function") {
d[name] = nop;
}
});
Object.freeze(d);
return d;
}
function allNames(obj) {
var names = Object.create(null); // Or use Map here
var thisObj;
for (thisObj = obj; thisObj; thisObj = Object.getPrototypeOf(thisObj)) {
Object.getOwnPropertyNames(thisObj).forEach(name => {
names[name] = 1;
});
}
return Object.keys(names);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
나는 모든 뮤 테이터 방법이로 시작 한다고 생각 하지만, 그렇지 않다면 위를 조정하는 것은 쉽습니다.Date
set
에서 의 MDN의 문서Object.freeze
(강조 광산) :
데이터 속성의 값은 변경할 수 없습니다. 접근 자 속성 (getter 및 setter)은 동일하게 작동하며 여전히 값을 변경하고 있다는 착각을줍니다. 개체 인 값도 고정되지 않는 한 수정할 수 있습니다.
Date 객체의 setTime
메서드는 Date 객체의 속성을 변경하지 않으므로 인스턴스를 고정 했음에도 불구하고 계속 작동합니다.
이것은 정말 좋은 질문입니다!
TJ Crowder의 대답 은 훌륭한 솔루션을 가지고 있지만 생각하게했습니다. 우리는 어떻게 돌아 다닐 수 Date.prototype.setTime.call(yourFrozenDate)
있습니까?
첫 번째 시도 : "래퍼"
한 가지 직접적인 방법은 AndrewDate
날짜를 래핑 하는 함수 를 제공하는 것입니다. 날짜에 세터를 제외한 모든 것이 있습니다.
function AndrewDate(realDate) {
var proto = Date.prototype;
var propNames = Object.getOwnPropertyNames(proto)
.filter(propName => !propName.startsWith('set'));
return propNames.reduce((ret, propName) => {
ret[propName] = proto[propName].bind(realDate);
return ret;
}, {});
}
var date = AndrewDate(new Date());
date.setMonth(2); // TypeError: d.setMonth is not a function
이것이 수행하는 모든 실제 날짜 객체가 가지고있는 특성과 용도를 가진 개체 만드는 것입니다 Function.prototype.bind
자신의 설정을 this
.
이것은 열쇠 주위에 모이는 바보 증거 방법은 아니지만 내 의도를 알 수 있기를 바랍니다.
하지만 잠깐 ... 여기저기서 조금 더 살펴보면 더 나은 방법이 있음을 알 수 있습니다.
두 번째 시도 : 프록시
function SuperAndrewDate(realDate) {
return new Proxy(realDate, {
get(target, prop) {
if (!prop.startsWith('set')) {
return Reflect.get(target, prop);
}
}
});
}
var proxyDate = SuperAndrewDate(new Date());
그리고 우리는 그것을 해결했습니다!
...sort of. See, Firefox is the only one right now which implements proxies, and for some bizarre reasons date objects can't be proxied. Furthermore, you'll notice that you can still do things like 'setDate' in proxyDate
and you'll see completions in console. To overcome that more traps need to be provided; specifically, has
, enumerate
, ownKeys
, getOwnPropertyDescriptor
and who knows what weird edge cases there are!
...So on second thought, this answer is nearly pointless. But at least we had fun, right?
You could wrap it in a class like structure and define custom getters and setters in order to prevent an undesired change
The accepted answer is actually flawed, I'm afraid. You actually can freeze an instance of any object including an instance of Date
. In support of @zzzzBov's answer, freezing an object instance does not imply the object's state becomes constant.
One way to prove that a Date
instance is truly frozen is by following the steps below:
var date = new Date();
date.x = 4;
console.log(date.x); // 4
Object.freeze(date);
date.x = 20; // this assignment fails silently, freezing has made property x to be non-writable
date.y = 5; // this also fails silently, freezing ensures you can't add new properties to an object
console.log(date.x); // 4, unchanged
console.log(date.y); // undefined
But you can achieve the behaviour I suppose you desire as follows:
var date = (function() {
var actualDate = new Date();
return Object.defineProperty({}, "value", {
get: function() {
return new Date(actualDate.getTime())
},
enumerable: true
});
})();
console.log(date.value); // Fri Jan 29 2016 00:01:20 GMT+0100 (CET)
date.value.setTime(0);
console.log(date.value); // Fri Jan 29 2016 00:01:20 GMT+0100 (CET)
date.value = null; // fails silently
console.log(date.value); // Fri Jan 29 2016 00:01:20 GMT+0100 (CET)
참고URL : https://stackoverflow.com/questions/34907311/is-there-a-way-to-object-freeze-a-javascript-date
'program story' 카테고리의 다른 글
Git & Intellij, 변경된 파일의 일부만 커밋하는 방법 (0) | 2020.10.22 |
---|---|
onConnected 함수가 호출 된 후 GoogleApiClient에서 "GoogleApiClient가 아직 연결되지 않았습니다"라는 메시지가 표시됨 (0) | 2020.10.22 |
Android에서 겹치는 뷰 (0) | 2020.10.22 |
Android View.GONE 가시성 모드에 해당하는 iOS (0) | 2020.10.22 |
다른 옵션보다 JCR (콘텐츠 저장소)을 언제 사용해야합니까? (0) | 2020.10.22 |