TIL DAY.43[コアJavaScript]データ型(2)
23122 ワード
今日は前回に続いてデータ型を勉強します.
データ型(2)
可変値
リファレンスデータをリファレンスデータのプロパティに再割り当てする場合は、ネストされたオブジェクト(nested object)を考慮します.
var obj = {
x: 3,
arr: [ 3, 4 ,5 ]
}
ここでobjarr[1]を検索するには、メモリ内のプロセスについて説明します.
1.まず、obj識別子を有するアドレスを変数領域で検索する.(1002)
2.変数領域の値を別のアドレスに移動します.(5001)
35001はデータ領域のアドレスであり、その値もアドレスに移動する.(7103~?)
4.オブジェクト変数領域7103~?に進み、arr識別子を持つアドレスを見つけます.(7104)
5.5003という名前のアドレスに移動します.(5003はデータ領域)
6.データ領域5003の値も8104から?移動先アドレスは.
7. 8104~?配列変数という名前の領域で、識別子1を持つアドレスを検索します.(8105)
8.識別子1のアドレスは8105であり、値は5004のデータ領域の値である.(5004)
9.データ領域におけるアドレス5004の値は4であり、デジタルデータ4を返す.
上の状態で下のように再割り当て命令を出したらどうなりますか?
obj.arr = 'str';
strは、データ領域の空白5006に格納され、arr識別子を有するアドレス7104値5006にアドレスが再割り当てされる.これにより、上記の5~9のプロセスは不要になり、参照カウント0のメモリアドレスになります.また、参照カウント0のメモリアドレスは、ゴミ収集器(ゴミ収集器)の収集対象となる.ゴミ収集器は、運転時の環境によって、ある時点やメモリ使用量が飽和状態に近いときに自動的に収集され、新しい値を割り当てることができる空きスペースになります.
レプリケーション変数の比較
まず、変数をコピーした後、オブジェクトのプロパティがどのように変更されるかを例に示します.
var a = 10;
var b= a;
var obj1 = { c: 10 , d:'ddd'};
var obj2 = obj1;
b = 15;
obj2.c = 20;
例えば、変数領域では、識別子aが値とともにスペース1001に格納される.識別子bも1002においてaと同じ値でコピーされ記憶される.obj 1と2であれば、前のように1003と1004に格納します.ただし、オブジェクトであるため、データ領域にはオブジェクト領域のアドレスが格納される.ゲスト領域では、7103〜7104が使用されることが保証される.
きほんデータ
そして、識別子bに対応するアドレス1002の値が10から15に変更され、空白データ領域に15の値を記憶する空間が作成される.すなわち、1002の変数領域で参照されるデータ値が変化する.
リファレンスデータ
識別子obj 2は、オブジェクト内のcという名前の値のみを10から20に変更します.これにより、変数領域では変化しませんが、オブジェクト領域で値を参照する部分が変化します.7103というアドレスの値が20になるからです.
もしこの両者の間に大きな違いがあれば
a != b
obj1 === obj2
つまり結果値です.基本データの場合、参照される値は変数領域で変更され、参照されるデータはオブジェクト変数領域で参照される値を変更するため、コピーされたobj 2が値を変更するとobj 1も変更されます.
もしobj 1!=結果値obj 2を表す場合はobj 2を使用します.obj 2={c:20,d:"ddd"}のようにオブジェクト自体を変更すると、新しいオブジェクト変数領域は8100から?obj 1として生成!=obj 2ではありません.
すなわち、参照データが「可変値」と記述されている場合、「可変」は、参照データ自体を変更するのではなく、その内部の輪郭を変更する場合にのみ成立します.
不変オブジェクト
不変オブジェクトを作成する簡単な方法
どのような場合にオブジェクトを変更する必要がありますか?
値として渡されるオブジェクトを変更しても、元のオブジェクトは変更されない場合があります.
次の2つの例では、オブジェクトを変更する必要があるかどうかを示します.var user = {
name: 'hokyun',
gender : 'male'
};
var changeName = function ( user, newName) {
var newUser = user;
newUser.name = newName;
return newUser;
};
var user2 = changeName(user, 'Jung');
if (user != user2) {
console.log('유저 정보가 변경되었습니다')
}
console.log(user.name, user2.name); // Jung Jung
console.log(user==user2); // true
上記の例では、changeName関数を使用してuserとjungというパラメータ値を受信し、userのname propertyを変更します.コンソールの結果値を表示します.nameとuser 2.同じ名前が表示されます.これは、オブジェクト自体を再宣言するのではなく、作成したオブジェクト変数領域内のPropertyのみを変更するためです.では、元のバージョンを保持しながら新しいuser 2を作成する方法を見てみましょう.var user = {
name: 'hokyun',
gender : 'male'
};
var changeName = function ( user, newName) {
return {
name: newName,
gender: user.gender
};
};
var user2 = changeName(user, 'Jung');
if (user != user2) {
console.log('유저 정보가 변경되었습니다') // 유저 정보가 변경되었습니다.
}
console.log(user.name, user2.name); // hokyun Jung
console.log(user==user2); // false
changeName関数は、新しいオブジェクトを返すように変更されました.これにより、userとuser 2は異なるオブジェクトであるため、変更前後を安全に比較することができる.
浅い放射と深い放射
浅い放射
var copyObject = function(target) {
var result = {};
for(var prop in target) {
result[prop] = target[prop];
}
return result;
};
var user = {
name : 'hokyun',
urls : {
portfolio: 'http//github.com/abc',
blog: 'http//blog.com',
facebook: 'http//facebook.com/abc'
}
};
var user2 = copyObject(user);
user2.name = 'Jung';
console.log(user.name === user2.name); //false
user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); // true
user2.urls.blog = '';
console.log(user.urls.blog === user2.url.blog); //true
上記の浅いレプリケーション方法のコンソールでは、userというオブジェクトのnameというpropertyを変更した場合、ソースファイルは変更されません.userの別のオブジェクトurlsの内容を変更すると、元のファイルも一緒に変更されていることがわかります.
すなわち、userオブジェクトに直接属するPropertyでは、完全に新しいデータがコピーされて作成され、さらに進んだURLの内部Propertyでは既存のデータが直接参照されます.
このような状況を避けるためにuser.urlsも不変のオブジェクトになるべきだ.
ふかほうしゃ
var copyObject = function(target) {
var result = {};
for(var prop in target) {
result[prop] = target[prop];
}
return result;
};
var user = {
name : 'hokyun',
urls : {
portfolio: 'http//github.com/abc',
blog: 'http//blog.com',
facebook: 'http//facebook.com/abc'
}
};
var user2 = copyObject(user);'
user2.urls = copyObject(user.urls);
user2.name = 'Jung';
console.log(user.name === user2.name); //false
user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); // false
user2.urls.blog = '';
console.log(user.urls.blog === user2.url.blog); //false
user2.urls=copyObject(user.urls)を使用してurls property内部にコピーし、新しいオブジェクトを作成します.
つまり、オブジェクトをコピーするときに、オブジェクトの内部のすべての値をコピーして完全に新しいデータを作成する場合は、オブジェクトのプロパティの値をコピーすることができます(この値が基本データである場合)、参照型データはオブジェクトの内部のプロパティを再コピーする必要があります.このプロセスは、参照型データがあるたびに再帰的に実行されてこそ、深さレプリケーションになります.
上記の概念に基づいて、深さレプリケーションでコードを変更するには、次のようにします.var copyObjectDeep = function(target) {
var result = {};
if (typeof target === 'object' && target !== null) {
for(var prop in target) {
result[prop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
};
3行目でtargetがオブジェクトである場合、copyObjectDeepは内部プログラムでループ呼び出し、オブジェクトでない場合は8行目でtargetを保持します.
マイ関数を使用してデプスコピー結果を確認
var obj = {
a: 1,
b: {
c: null,
d: [1,2]
}
}
var obj2 = copyObjectDeep(obj);
obj2.a = 3;
obj2.b.c = 4;
obj.b.d[1] = 3;
console.log(obj); // {a: 1 , b: {c: null, d:[1,3]}}
console.log(obj2); // {a :3, b:{c:4, d:{0:1,1:2}}}
未定義とnull
JAvascriptには未定義とnull値があり、「なし」を表します.2つの値の意味は同じようですが、細かく異なり、使用目的も異なります.
var user = {
name: 'hokyun',
gender : 'male'
};
var changeName = function ( user, newName) {
var newUser = user;
newUser.name = newName;
return newUser;
};
var user2 = changeName(user, 'Jung');
if (user != user2) {
console.log('유저 정보가 변경되었습니다')
}
console.log(user.name, user2.name); // Jung Jung
console.log(user==user2); // true
var user = {
name: 'hokyun',
gender : 'male'
};
var changeName = function ( user, newName) {
return {
name: newName,
gender: user.gender
};
};
var user2 = changeName(user, 'Jung');
if (user != user2) {
console.log('유저 정보가 변경되었습니다') // 유저 정보가 변경되었습니다.
}
console.log(user.name, user2.name); // hokyun Jung
console.log(user==user2); // false
var copyObject = function(target) {
var result = {};
for(var prop in target) {
result[prop] = target[prop];
}
return result;
};
var user = {
name : 'hokyun',
urls : {
portfolio: 'http//github.com/abc',
blog: 'http//blog.com',
facebook: 'http//facebook.com/abc'
}
};
var user2 = copyObject(user);
user2.name = 'Jung';
console.log(user.name === user2.name); //false
user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); // true
user2.urls.blog = '';
console.log(user.urls.blog === user2.url.blog); //true
var copyObject = function(target) {
var result = {};
for(var prop in target) {
result[prop] = target[prop];
}
return result;
};
var user = {
name : 'hokyun',
urls : {
portfolio: 'http//github.com/abc',
blog: 'http//blog.com',
facebook: 'http//facebook.com/abc'
}
};
var user2 = copyObject(user);'
user2.urls = copyObject(user.urls);
user2.name = 'Jung';
console.log(user.name === user2.name); //false
user.urls.portfolio = 'http://portfolio.com';
console.log(user.urls.portfolio === user2.urls.portfolio); // false
user2.urls.blog = '';
console.log(user.urls.blog === user2.url.blog); //false
var copyObjectDeep = function(target) {
var result = {};
if (typeof target === 'object' && target !== null) {
for(var prop in target) {
result[prop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
};
var obj = {
a: 1,
b: {
c: null,
d: [1,2]
}
}
var obj2 = copyObjectDeep(obj);
obj2.a = 3;
obj2.b.c = 4;
obj.b.d[1] = 3;
console.log(obj); // {a: 1 , b: {c: null, d:[1,3]}}
console.log(obj2); // {a :3, b:{c:4, d:{0:1,1:2}}}
ユーザが「空」を明示的に表したい場合はnullを使用します.これは、この目的で最初に使用されたデータ型です.
変数に値が存在しない場合はundefinedを使用します.
Reference
この問題について(TIL DAY.43[コアJavaScript]データ型(2)), 我々は、より多くの情報をここで見つけました https://velog.io/@kyman19940214/TIL-DAY.43-코어-자바스크립트-데이터-타입-2テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol