[ydkjs]this & Object Prototypes-3-Object

Object

Syntax

Object의 두가지 형식.
constructed가 property를 하나씩 추가 가능하다는 것 외엔 전부 동일.

//literal
var obj = {
	key: value,
};
// constructed form
var myObj = new Object();
myObj.key = value;

Type

language types

  • string
  • number
  • boolean
  • null
  • undefined
  • object

Built-in Objects

object sub-types

  • String
  • Number
  • Boolean
  • Object
  • Function
  • Array
  • Date
  • RegExp
  • Error

실제로 built-in function이다. constructor로 사용가능하다.(new를 사용하여 새로 constructed object가 만들어진다)

var strPrimitive = "I am a string";
typeof strPrimitive;	// "string"
strPrimitive instanceof String;	// false

var strObject = new String( "I am a string" );
typeof strObject; 	  // "object"
strObject instanceof String;		// true

// inspect the object sub-type
Object.prototype.toString.call( strObject );	// [object String]

"hi" 이런 것은 객체가 아니지만, 여기서 작업을 하기 위해서(길이, contents 접근) String 객체가 필요할 때가 있는데, 다행히도 필요하다면 자동으로 연결된다.
number, boolean 등 도 마찬가지인데 null, undefined는 wrapper form이 없고, Date 같은 경우에는 constructed object form으로만 생성이 가능하다.
construted form이 더 많은 옵션이 있지만 필요할 때가 아니면 사용하지 말자.
Error는 보통 자동으로 만들어진다.

Contents

객체의 property는 value가 저장되어 있는 곳에 대한 포인터처럼 동작한다.(속해 있기 보다는)
. [""]을 이용하여 접근가능하다.

property 이름은 항상 string이다. 다른 유형을 써도 자동으로 바뀐다.

Computed Property Names

literal 선언에서, key-name 위치에서[]로 감싸면 표현식을 이용하여 이름을 만들 수 있다.

그리고 더 흔한 사용으로는 Symbol을 이용할 수 있다. 간단하게 말해서 추측 불가의 string 유형의 이름을 만들어 준다.?

var myObject = {
	[Symbol.Something]: "hello world"
};

Property vs. Method

객체에 들어있는 함수를 method라고 한다.

Arrays

array를 object로 쓸 거면 뭐하러..

var myArray = [ "foo", 42, "bar" ];

myArray.baz = "baz";

myArray.length;	// 3

myArray.baz;	// "baz"
//["foo", 42, "bar", baz: "baz"]
var myArray = [ "foo", 42, "bar" ];

myArray["3"] = "baz";

myArray.length;	// 4

myArray[3];		// "baz"
//["foo", 42, "bar", "baz"]

Duplicating Objects

function anotherFunction() { /*..*/ }

var anotherObject = {
	c: true
};

var anotherArray = [];

var myObject = {
	a: 2,
	b: anotherObject,	// reference, not a copy!
	c: anotherArray,	// another reference!
	d: anotherFunction
};

anotherArray.push( anotherObject, myObject );

shallow copy라면, a는 2로 그대로 복사하겠지만 나머지는 그냥 기존 객체의 참조를 가져올 것 이다.

deep copy라면, myObject뿐 아니라 anotherObject, anotherArray도 복사하는데 그럼 circular reference. deep copy..

JSON 방법

var newObj = JSON.parse( JSON.stringify( someObj ) );

Object.assign()으로 shallow copy를 할 수 있다.

var newObj = Object.assign( {}, myObject );

newObj.a;						// 2
newObj.b === anotherObject;		// true
newObj.c === anotherArray;		// true
newObj.d === anotherFunction;	// true

Property Descriptors

var myObject = {
	a: 2
};

Object.getOwnPropertyDescriptor( myObject, "a" );
// {
//    value: 2,
//    writable: true,
//    enumerable: true,
//    configurable: true
// }
var myObject = {};
//보통 사용하지 않음
Object.defineProperty( myObject, "a", {
	value: 2,
	writable: true,
	configurable: true,
	enumerable: true
} );

myObject.a; // 2

Writable

var myObject = {};

Object.defineProperty( myObject, "a", {
	value: 2,
	writable: false, // not writable!
	configurable: true,
	enumerable: true
} );

myObject.a = 3;
//"use strict"; TypeError// setter와 비슷.

myObject.a; // 2

Configurable

strict mode와 상관없이 해당 부분이 false라면 definedProperty 를 쓸 때, TypeError. 취소 불가능.

그런데 .. false여도 writable을 에러없이 true에서 false로 가능하다. 반대는 불가능.

그리고 delete을 막을 수 있다. delete은 다른 언어에서처럼 메모리 해제하는 것이 아니라 지울 수 있는 객체 속성을 지우는 것 뿐이다.

myObject.a;				// 2
delete myObject.a;
myObject.a;				// 2

Enumerable

열거 가능한지에 대한....

Immutability

property에 다른 참조가 포함되어 있는 경우, 해당 property가 변경 불가능이라고 해도, 값을 바꿀 수 있다.

Object Constant

writable:false && configurable:false

Prevent Extensions

객체 내부가 변하는 것을 막고 싶다면 Object.preventExtensions(객체) . strict mode에서 시도하면 TypeError

Seal

Object.seal()는 sealed 객체를 만든다. 즉, Object.preventExtensions(객체)configurable:false를 적용한다.

Freeze

Object.freeze() seal에서 writable:false를 추가하지만 처음에 언급했듯이 참조된 객체는 영향을 받지 않는다.

[[Get]]

var myObject = {
	a: 2,
	c: undefined
};

myObject.a; // 2
myObject.b; // undefined// No Error
myObject.c; // undefined// 윗줄과 결과가 똑같은데 어떻게 구별?

실제로 [[Get]]()이 동작한 것. 처음에 요청받은 이름의 속성에 대해 객체 property를 조사하고, 찾았다면 value를 반환한다. 찾지 못했다면 "undefined" return.

[[Put]]

이미 있거나 새로운 property 설정 방법을 통제한다.

property가 존재할 경우,
1. Is the property an accessor descriptor? 맞으면 setter call.
2. Is the property a data descriptor with writable of false? 맞으면 실패.
3. 다른 경우엔, 정상작동.

Getters & Setters

ES5부터 getter, setter를 이용하여 객체 수준이 아닌 property 수준의 default 작동을 override할 수 있게 되었다.
getter는 값을 찾기 위해, setter는 값을 설정하기 위해 함수를 호출하는 property.
이런 getter나 setter를 속성으로 정의하면 이것을 "accessor descriptor"라고 하고, 이 경우 value, writable이 무시되고 대신에 JS는 get, set을 사용한다.

var myObject = {
	// define a getter for `a`
	get a() {
		return 2;
	}
};

Object.defineProperty(
	myObject,	// target
	"b",		// property name
	{			// descriptor
		// define a getter for `b`
		get: function(){ return this.a * 2 },

		// make sure `b` shows up as an object property
		enumerable: true
	}
);

myObject.a; // 2

myObject.b; // 4

myObject.a = 3;//setter가 유효하다고 하더라도 .... 결과는 아래와 같다.

myObject.a; // 2

getter와 setter는 같이.

var myObject = {
	// define a getter for `a`
	get a() {
		return this._a_;
	},

	// define a setter for `a`
	set a(val) {
		this._a_ = val * 2;
	}
};

myObject.a = 2;

myObject.a; // 4

Existence

아까 위에서 실제로 없는지, 혹은 값이 undefined인지 구별을 어떻게 할까?
in은 property가 [[Prototype]] 수준에서 존재하는지, 객체 안에 존재하는지. (property name)
hasOwnProperty()는 후자만. 이는 Object.prototype에 연결되어 있는데 Object.create(null)을 이용하면 실패할 것.그럼 확실하게 Object.prototype.hasOwnProperty.call(myObject,"a")

var myObject = {
	a: 2
};

("a" in myObject);				// true
("b" in myObject);				// false

myObject.hasOwnProperty( "a" );	// true
myObject.hasOwnProperty( "b" );	// false

Enumeration

var myObject = { };

Object.defineProperty(
	myObject,
	"a",
	// make `a` enumerable, as normal
	{ enumerable: true, value: 2 }
);

Object.defineProperty(
	myObject,
	"b",
	// make `b` NON-enumerable
	{ enumerable: false, value: 3 }
);

myObject.b; // 3
("b" in myObject); // true
myObject.hasOwnProperty( "b" ); // true

// .......

for (var k in myObject) {
	console.log( k, myObject[k] );
}
// "a" 2
//직접적으로 알려줌
myObject.propertyIsEnumerable( "a" ); // true
myObject.propertyIsEnumerable( "b" ); // false
//key는 가능한 것들만 나옴.
Object.keys( myObject ); // ["a"]
Object.getOwnPropertyNames( myObject ); // ["a", "b"]

Iteration

forEach() : 배열의 모든 값들을 반복, 콜백 반환값 무시
every() : 끝까지, 콜백이 falsy값을 반환하면 멈춘다.
some(): 끝가지, 콜백이 truthy 값을 줄 때까지 돈다.

for...of array의 value에 직접.

@@iterator

var myObject = {
	a: 2,
	b: 3
};

Object.defineProperty( myObject, Symbol.iterator, {
	enumerable: false,
	writable: false,
	configurable: true,
	value: function() {
		var o = this;
		var idx = 0;
		var ks = Object.keys( o );
		return {
			next: function() {
				return {
					value: o[ks[idx++]],
					done: (idx > ks.length)
				};
			}
		};
	}
} );

// iterate `myObject` manually
var it = myObject[Symbol.iterator]();
it.next(); // { value:2, done:false }
it.next(); // { value:3, done:false }
it.next(); // { value:undefined, done:true }

// iterate `myObject` with `for..of`
for (var v of myObject) {
	console.log( v );
}
// 2
// 3

좋은 웹페이지 즐겨찾기