//방법1.

function Car(name,color){

this.name = name;

this.color = color;

this.show = function(){console.log(name, color)}

}


var car1 = new Car('morning','blue');

car1.show();



//방법2. 프로토타입 이용


function BigCar(name, color){

this.name = name;

this.color = color;

}


BigCar.prototype.show = function(){

console.log('bigcar' ,this.name , this.color)

}

//자식 객체 1

var bigcar1 = new BigCar('churare','white');

bigcar1.show();

//자식 객체 2

var bigcar2 = new BigCar('dump','black');

bigcar2.show();



//방법3. 객체리터럴(싱글톤)

var smallcar = {

name: "tico",

color: "blue",

show: function(){

console.log('smallcar',this.name,this.color);

}

}

//할당

smallcar.name = "morning2";

smallcar.color = "gold";

smallcar.show();



//*******************************************************js getter setter 1************************************************

var person = {

    firstName: 'Jimmy',

    lastName: 'Smith',

    get fullName() {

        return this.firstName + ' ' + this.lastName;

    },

    set fullName (name) {

        var words = name.toString().split(' ');

        this.firstName = words[0] || '';

        this.lastName = words[1] || '';

    }

}


person.fullName = 'Jack Franklin';

console.log(person.firstName); // Jack

console.log(person.lastName) // Franklin



//*******************************************************js getter setter 2****************************************************

var person2 = {

    firstName: 'kang',

    lastName: 'youngkyuen'

};


Object.defineProperty(person2, 'fullName', {

    get: function() {

        return this.firstName + ' ' + this.lastName;

    },

    set: function(name) {

        var words = name.split(' ');

        this.firstName = words[0] || '';

        this.lastName = words[1] || '';

    }

});

console.log(person2.fullName) 



//********************************************************************************************




//------------------------------------------

function Student(name, age) {

    this.name = name;

     

    this.getName = function() {

        return this.name;

    }

    this.setName = function(name) {

        this.name = name;

    }

}

var preamtree = new Student(name);



//------------------------------------------

function Student(name, age) {

    this.name = name;

}

Student.prototype.getName = function() {

    return this.name;

}

 

Student.prototype.setName = function(name) {

    this.name = name;

}

var preamtree = new Student(name);


//---------------------------------------------------------------------------

//prototype에 프로퍼티를 추가하는 함수

Function.prototype.method = function(name, func) {

    if(!this.prototype[name]) {

        this.prototype[name] = func;

    }

}

 

function Person(name, age) {

    this.name = name;

}

 

// prototype에 프로퍼티를 추가할 때마다 '.prototype'을 반복할 필요가 없음.

Person.method('getName',  function() {

    return this.name;

});

 

Person.method('setName', function(name) {

    this.name = name;

});



//********************************* 상속 *********************************


//부모 클래스

function Car(name,color){

this.name = name;

this.color = color;

this.show = function(){

return this.name + ' ' + this.color;

}


}



function create(o) {

    function F() {}; //빈 자식 클래스

    F.prototype = o;

    return new F(); // o를 부모로하는 객체 리턴

}


var myPcar = new Car('pCar','BLACK');

var sunCar = create(myPcar);

var text = sunCar.show();

console.log(text);



  1. 2018.10.17 16:14

    비밀댓글입니다

자바스크립트로 블록체인 구현 강좌 11 - 나만의 비트코인 발행하기

지난 포스팅에서 하나의 네트워크에서 블록체인이 어떻게 작동이 되는지 살펴보았다. 이번포스팅에서는 여러개의 노드, 즉 컴퓨터들이 참여를 할때 블록체인 데이터가 어떻게 기록되는지 살펴보겠다.

순서

1. api.js 파일 이름을 networkNode.js 로 변경하자. 

2. networkNode.js 파일 윗 부분에 동적 포트관련 변수 선언해준다.

//동적 포트 package.json script 객체에서 2번째 방에 들어있는 데이터 3001,3002,3003 ...3005
var port = process.argv[2];

3. app.listen 을 아래와 같이 바꿔 준다.

//동적 포트
app.listen(port,function(){
console.log(`listening on port ${port}...`)
})

4. package.json 부분에서 script 부분을 아래와 같이 바꿔 준다.

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"node_1":"nodemon --watch dev -e js dev/networkNode.js 3001 http://localhost:3001",
"node_2":"nodemon --watch dev -e js dev/networkNode.js 3002 http://localhost:3002",
"node_3":"nodemon --watch dev -e js dev/networkNode.js 3003 http://localhost:3003",
"node_4":"nodemon --watch dev -e js dev/networkNode.js 3004 http://localhost:3004",
"node_5":"nodemon --watch dev -e js dev/networkNode.js 3005 http://localhost:3005"
},



이제 포트 3001 부터 3005번 까지의 node(서버)를 실행시킬 수 있다. 실행방법은 아래와 같다.

1. 터미널 열기 

2. 개발폴더에 위치하고

3. npm run node_1

4. 터미널 창 하나 더 뛰워서 npm run node_2  반복적으로 실행



blockchain.js로 이동

//sha256 모듈을 가져다 쓰겠다.
const sha256 = require('sha256');

//현재 노드의 url -- package.json script 객체에서 3번째 방에 들어있는 데이터 http://localhost:3001
const currentNodeUrl = process.argv[3];

//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.pendingTransaction = [];
//현재 node url -- 이부분!!!
this.currentNodeUrl = currentNodeUrl;
this.networkNodes = [];

//제네시스 블락 - 임의의 인자값 넣어준다.
this.createNewBlock(100,'0','0')
}


sha 256모듈 변수 아래에 현재 노드의 url을 알 수 있는 코드를 작성하고 function blockchain(){} 함수 안에 //현재 node url 주석 아래 두 코드를 작성해준다. 이건 접속한 node의 url 데이터를 저장하겠다는 뜻.


새로운 노드가 기존의 네트워크에 진입하는과정 (탈중앙화된 네트워크 그림)

1. 새로운 노드가 기존의 노드 네트워크에 들어가기전에 등록을 거친 후 알린다.

2. 각 노드들에게 새로운 노드 정보를 등록시켜 준다.

3.기존의 모든 노드의 데이터를 새로운 노드에게 등록한다.


소스(networkNode.js에 작성)

//새로운 노드를 등록하고 전체 네트워크에 알림
app.post('/register-and-broadcast-node',function(req,res){

})
// 네트워크에 새로운 노드 등록
app.post('/register-node',function(req,res){

})
// 새로운 노드에 기존의 노드 정보 등록
app.post('/register-nodes-bulk',function(req,res){

})


npm promise api 설치 - js에서 비동기작업을 순차적으로 or 병렬로 처리가능하게 컨트롤하는 모듈


npm install request-promise --save

npm install request --save


둘다 입력!



promise 에 대한 자세한 설명

http://programmingsummaries.tistory.com/325

모듈 임포트

맨위쪽에 promise 모듈을 사용할 변수 설정

//request-promise 모듈
var rp = require('request-promise');


새로운 노드를 전체 노드에 등록하고 알리는 코드작성

//새로운 노드를 등록하고 전체 네트워크에 알림
app.post('/register-and-broadcast-node',function(req,res){
//새로 진입한 노드 주소
const newNodeUrl = req.body.newNodeUrl;
//비트코인 네트워크에 새로 진입한 노드의 주소가 없을 경우 추가
if(bitcoin.networkNodes.indexOf(newNodeUrl) == -1){
bitcoin.networkNodes.push(newNodeUrl);
}
const regNodesPromises = [];
//비트코인 네트워크에 등록된 네트워크에 새로운 노드 정보를 등록
bitcoin.networkNodes.forEach(networkNodes => {
//register - node
const requestOption = {
uri: networkNodesUrl + '/register-node',
method: 'POST',
body:{newNodeUrl:newNodeUrl},
json:true
};
//순차적으로 비동기를 실행하기 위해서 배열에 넣음
regNodesPromises.push(rp(requestOption))
}); //for 문 끝

//순차적으로 비동기 작업 처리
Promise.all(regNodesPromises)
.then(data => {
//새로운 노드안에 전체 네트워크에 대한 정보 한번에 입력해주기
const bulkRegisterOption = {
uri : newNodeUrl + '/register-nodes-bulk',
method : 'POST',
body : {allNetworkNodes : [...bitcoin.networkNodes,bitcoin.currentNodeUrl]},
json : true
};
return rq(bulkRegisterOption);
}).then(data => {
res.json({nodt: "새로운 노드가 전체 네트워크에 성공적으로 등록이 되었습니다."});

});
});


전체 네트워크에 새로운 노드 등록하는 코드

// 네트워크에 새로운 노드 등록
app.post('/register-node',function(req,res){
//새로운 노드 주소
const newNodeUrl = req.body.newNodeUrl;
//코인 네트워크에 새로운 노드의 주소가 없다면,
const nodeNotAlreadyPresent = bitcoin.networkNodes.indexOf(newNodeUrl) == -1;
//코인의 현재 url이 새로운 노드 주소가 아니라면, 즉 현재 접속한 주소와 중복되지 않는다면,
const notCurrentNode = bitcoin.currentNodeUrl !== newNodeUrl;

if(nodeNotAlreadyPresent&&notCurrentNode){
//코인 전체 네트워크에 새로운 주소 등록
bitcoin.networkNodes.push(newNodeUrl);
res.json({note: "새로운 노드가 등록되었습니다."})
}

})


결과확인

3001-3005번 서버를 다 작동시킨다.

웹브라우저에 https://localhost:3001/blockchain 입력후 확인


postman을 열어서 body로 json 데이터 전송

 

웹브라우저 다시 확인


마무리


다른 주소로도 여러번 테스트 해보자. 다음 포스팅에서 마저 정리하도록 하겠다.



  1. 기웃거리는 개발자 2018.06.14 18:03

    한수 잘 배웠습니다.. 직접 코딩 해봐야 데이터 처리 흐름에 개념이 오네요.ㅎㅎ
    감사합니다~

  2. kebi300 2018.06.29 13:53

    안녕하세요. 덕분에 많은 것을 배우고 가요.

    근데 register-and-broadcast-node 부분은 아직 작동안하는데, 다음 포스트에서 하시나요?

    그리고 forEach 구문에서 networkNodes=> 이 아니라 networkNodesUrl=>

    아닌가요? 오타인듯 해서요.

    좋은 포스팅 감사합니다.


    bitcoin.networkNodes.forEach(networkNodes => {
    //register - node
    const requestOption = {
    uri: networkNodesUrl + '/register-node',
    method: 'POST',
    body:{newNodeUrl:newNodeUrl},
    json:true
    };
    //순차적으로 비동기를 실행하기 위해서 배열에 넣음
    regNodesPromises.push(rp(requestOption))
    })

  3. ㅇㅁㄴ 2018.08.09 16:55

    TREBIT

    코인거래소
    Trebit 이 원화마켓을 오픈합니다 :)
    8월 8일 18시 기준 원화마켓이 오픈이 되었습니다 !

    원화(KRW)마켓 오픈과 함께
    옵저버(OBSR)와 아이온(ION) 8월10일 상장!!!

    특히 옵저버(OBSR)는 전 세계 최초로 트래빗 거래소에 상장되는 코인으로,

    일반 암호화폐와 다르게
    ICO를 진행하지 않고 상장되는 종목입니다.

    원화(KRW)마켓 오픈 기념으로
    거래수수료 0% 이벤트를 진행 중이니
    수수료 부담 없이 거래하시고,
    무려 3억원 상당의
    에어드랍 이벤트의 주인공에 도전해 보세요.

    트래빗고객센터 : 1600-5433
    운영시간 : 평일 09:00 ~ 18:00
    이용문의 : cs@trebit.com

    *옵저버 더 알아보기: http://www.obsr.org/index
    *아이온 더 알아보기: https://ionomy.com/games

  4. 코더 2018.08.28 22:25

    포스팅 정말 감사드립니다 자바스크립트로 코인 만들어보고 싶었는데 이렇게 이해하기 쉽게 올려주셔서ㅜㅜ

  5. 굿굿 2019.03.11 14:05

    다 따라해보면서 하는데도 아리송한 부분도 있고

    덕분에 깨우친 부분도 있었습니다

    하지만 js로 이정도 퀼리티로 설명해주는곳은 얼마 없으며

    저를 이해시키다니!! 대단하십니당ㅎㅎㅎ

    강좌 12강을 기다리고 있습니다ㅠㅠㅠ

    아니면 제가 배운것을 응용해서 만들어보는것도 나쁘지 않겠지요

    잘 배웠습니다.!!

    • ㅇㅇ 2019.03.11 19:51

      11번쪽은 예제를 두세번 따라하고 오타를 전부 잡았음에도 불구하고 Postman 결과값이 Cannot POST /blockchain/register-node 이나오네요 ...

      왜일까요 마지막인데 속상하네요ㅠㅠ

자바스크립트로 블록체인 구현 강좌4 - 나만의 비트코인 발행하기


지난 포스팅에 이어서 이번시간에는 저번 포스팅에서 작성한 마지막 블락 가져오기 함수와 새로운 트랜젝션 생성하기 함수를 test.js 에서 한번 찍어 보겠다. 그리고 트랜잭션과 새로운 블락이 생겼을 때 , 그리고 새로운 블록이 생긴 이후 트랜잭션 데이터는 어떻게 변하는지 이 관계를 살펴보도록 하자.


test.js로 이동해서 새로운 블락을 생성하는 함수와 새로운 트랜젝션을 생성하는 함수를 하나씩 작성한다.


//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.

const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");

//새로은 트랜잭션 생성 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(100,'PACKadffaaf','HONGllalflks')

//찍어보기
console.log(bitcoin)


//결과
/*
Blockchain {
chain:
[ { index: 1,
timestamp: 1527228481937,
transactions: [],
nonce: 1111,
hash: '1a1a1a1a1a1a',
previousBlockHash: 'aaaaaaa' } ],
pendingTransaction:
[ { amount: 100, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ] }
*/

위의 코드에서 주석처리된 결과 부분을 보자

새로운 블락인 index 1 은 chain 배열에 객체 형태로 들어갔다. 

그뒤 발생한 새로운 트랜젝션 은 pendingTransaction 배열에 객체 형태로 들어갔다.

그래서? 이게 뭐? 라고 생각할 수도 있다. 일단은 지금까지 이론으로만 알았던 '블록 하나에  거래내역을 저장한다' 라는 말이 조금 이해가 될것이다. 

그래서 블록체인을 공용장부라고 한다. 일단은 지금 index 1 블록의 transaction[]은 비어있다. 그렇다면 지금 pendingTransaction에 있는 거래 데이터를 어떻게 index : 1 인 블록의 transaction에 기록할까? 채굴을 해야 한다. 이말은 새로운 블락이 하나더 생성이 되면 그 새로운 블락의 transaction에 지금의 미완료된 트랜젝션이 기록된다는 뜻이다.

//새로은 트랜잭션 생성 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(100,'PACKadffaaf','HONGllalflks') 이 코드 아래에 추가


//새로운 블락 생성 - 채굴후 얻은 블락
bitcoin.createNewBlock(2222,"bbbbbbb","2b2b2b2b2b2b");


새로운 블록이 추가 되었다. 한번 찍어보자. 뚜둥. 결과 값은 아래와 같다. 위에서 발생한 pendingTransaction 거래 기록은 새로 생성된 index 2 인 블록의 transaction[] 배열에 들어 갔다. 지금은 [Array] 이렇게 표시가 되어 있는데 저 부분만 한번 찍어보자.

//결과
/*
Blockchain {
chain:
[ { index: 1,
timestamp: 1527229062594,
transactions: [],
nonce: 1111,
hash: '1a1a1a1a1a1a',
previousBlockHash: 'aaaaaaa' },
{ index: 2,
timestamp: 1527229062594,
transactions: [Array],
nonce: 2222,
hash: '2b2b2b2b2b2b',
previousBlockHash: 'bbbbbbb' } ],
pendingTransaction: [] }

*/


index : 2 블록 부분만 찍어보았다. 아래에. transactions 배열 부분을 보자. 위에서 봤던 pendingTransaction의 객체 형태의 데이터가 들어가 있다.

//찍어보기
console.log(bitcoin.chain[1])


//결과
/*
{ index: 2,
timestamp: 1527229359157,
transactions:
[ { amount: 100, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ],
nonce: 2222,
hash: '2b2b2b2b2b2b',
previousBlockHash: 'bbbbbbb' }

*/


이제 대충 감이 올것이다. 추가로 트랜젝션을 더 발생시켜보자. 위에서 작성한 새로운 블락 만드는 소스 아래에 소스 코드를 추가해준다.

//새로은 트랜잭션 생성2 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(777,'PACKadffaaf','HONGllalflks')
//새로은 트랜잭션 생성3 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(888,'PACKadffaaf','HONGllalflks')
//새로은 트랜잭션 생성4. - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(999,'PACKadffaaf','HONGllalflks')



그리고 다시 node 명령어로 실행을하고 결과를 보자. 위에서 발생한 트랜젝션 3건 데이터가 어디에 있는가? 이것만 빨리 캐치하면 된다. pendingTransaction 배열에 있다. 아직 미완결된 거래이기 때문에 일단 저기 들어가 있다. 그러면 저 데이터가 블락안에 들어가서 신뢰할 수 있는 데이터가 되려면 어떻게 해야 하나? 컴퓨팅 파워로 암호를 풀어서 생성해주면 된다. 일단 지금은 컴퓨팅 파워를 엄청 써서 새로운 블락을 또 생성했다고 가정하자. 또 새로운 블락이 생성이 되었기 때문에 해당 코드를 한번 더 작성해보자.


//찍어보기
console.log(bitcoin)


//결과
/*
Blockchain {
chain:
[ { index: 1,
timestamp: 1527229704057,
transactions: [],
nonce: 1111,
hash: '1a1a1a1a1a1a',
previousBlockHash: 'aaaaaaa' },
{ index: 2,
timestamp: 1527229704057,
transactions: [Array],
nonce: 2222,
hash: '2b2b2b2b2b2b',
previousBlockHash: 'bbbbbbb' } ],
pendingTransaction:
[ { amount: 777, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 888, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 999, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ] }

*/


마이닝으로 새로운 블락이 생성되었다.

//새로운 블락 만들기
bitcoin.createNewBlock(3333,"ccccccc","3c3c3c3c3c3c");


이전 거래들이 어떻게 이동이 되는지 자세히 보라. pendingTransaction[] 에 일단 값들이 보이지 않는다. 그리고 index:3 블록 transactions[] 에 Array 배열 값이 생겼다. 이제 거의 감을 잡았으리라 생각한다. 찍어보자.

console.log(bitcoin)


//결과
/*
Blockchain {
chain:
[ { index: 1,
timestamp: 1527229993383,
transactions: [],
nonce: 1111,
hash: '1a1a1a1a1a1a',
previousBlockHash: 'aaaaaaa' },
{ index: 2,
timestamp: 1527229993384,
transactions: [Array],
nonce: 2222,
hash: '2b2b2b2b2b2b',
previousBlockHash: 'bbbbbbb' },
{ index: 3,
timestamp: 1527229993384,
transactions: [Array],
nonce: 3333,
hash: '3c3c3c3c3c3c',
previousBlockHash: 'ccccccc' } ],
pendingTransaction: [] }
*/


index : 3 블록만 찍어보았다. 이전 거래내역들이 새로 생성된 블락으로 이동한것을 볼 수 있다.

//찍어보기
console.log(bitcoin.chain[2])


//결과
/*
{ index: 3,
timestamp: 1527230266389,
transactions:
[ { amount: 777, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 888, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 999, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ],
nonce: 3333,
hash: '3c3c3c3c3c3c',
previousBlockHash: 'ccccccc' }
*/


혹시나해서 test.js의 전체 코드를 올려놓는다.

//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");

//새로은 트랜잭션 생성 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(100,'PACKadffaaf','HONGllalflks')


//새로운 블락 생성 - 채굴후 얻은 블락(마이닝)
bitcoin.createNewBlock(2222,"bbbbbbb","2b2b2b2b2b2b");

//새로은 트랜잭션 생성2 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(777,'PACKadffaaf','HONGllalflks')
//새로은 트랜잭션 생성3 - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(888,'PACKadffaaf','HONGllalflks')
//새로은 트랜잭션 생성4. - (총금액, 보내는이, 받는이)
bitcoin.createNewTransaction(999,'PACKadffaaf','HONGllalflks')


//새로운 블락 만들기
bitcoin.createNewBlock(3333,"ccccccc","3c3c3c3c3c3c");




//찍어보기
console.log(bitcoin.chain[2])


//결과
/*
{ index: 3,
timestamp: 1527230266389,
transactions:
[ { amount: 777, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 888, sender: 'PACKadffaaf', recipient: 'HONGllalflks' },
{ amount: 999, sender: 'PACKadffaaf', recipient: 'HONGllalflks' } ],
nonce: 3333,
hash: '3c3c3c3c3c3c',
previousBlockHash: 'ccccccc' }
*/









!!만약에 이 포스팅을 보면서 따라 해봤는데도 이해가 안간다면 이것만 기억하자. 

1.거래가 발생하면 트랜잭션 데이터가 생긴다.

2.이 데이터는 아직 신뢰할 수 없다.

3.어떻게 해야하나? -> 채굴자들이 마이닝을 해서 새로운 블락을 생성해야 한다.

4.새로운 블락이 생성되었다.

5.이전 트랜잭션 데이터는 새로운 블락에 쓰여지면서 신뢰할 수 있게된다.




  1. JHY 2019.08.01 18:21

    오 중간정리까지 꼼꼼하게 잘 올려주셔서 그나마 이해가 잘 되요 다른 댓글들이 말씀하신 것처럼.....ㅎㅎㅎ

자바스크립트로 블록체인 구현 강좌2 - 나만의 비트코인 발행하기


지난 포스팅에서는 자바스크립트로 블록체인 구현을 위한 셋팅과 자바스크립트의 데이터구조와 프로토타입에 대한 기본 지식을 알아보았다. 이번에는 지난번 포스팅에서 구현한 내용을 직접 console.log로 찍어보면서 대충 아~ 이런거구나 하고 감을 잡아보자

blockchain.js  모듈화 하기

//블록체인 데이터 구조
function Blockchain(){
this.chain = [];
this.newTransactions = [];
}


//블록체인 프로토 타입 함수 정의
Blockchain.prototype.createNewBlock = function(nonce,previousBlockHash,hash){
//새 블록 객체
const newBlock = {
index: this.chain.length + 1,
timestamp: Date.now(),
transactions: this.newTransactions,
nonce:nonce,
hash:hash,
previousBlockHash:previousBlockHash
};

//다음 거래를 위한 거래내역 배열 비워주고 새로운 블록을 chin 배열에 추가
this.newTransactions = [];
this.chain.push(newBlock);

return newBlock;

}

//Blockchain 모듈화
module.exports = Blockchain;

module.exports = Blockchain으로 다른 페이지에서도 이 모듈을 사용할 수 있게 해준다.


test.js 로 이동. 

아래와 같이 코드를 작성해준다. 위에서 작성한 블록체인 코드를 여기서 테스트 해보겠다는 뜻이다. 그리고 실행해보자.

//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//찍어보기
console.log(bitcoin)


 node 명령어로 실행해보기 

 node 명령어로 실행한거 확인해보기 -  짜쟌


저게 먼지는 아직 잘 몰라도 일단 콘솔에 우리가 적은 코드랑 비스무리한게 떴다.

자 그럼 이제 직접 새로운 블락을 생성해보자

주석으로 새로운 블락 만들기를 보자. createNewBlock은 앞 포스팅에서 만들어놓은 프로토 타입 함수다. 인자값으로 일단 아무 값이나 넣어주었다.

//blockchain.js 모듈을 이곳에서 가져다 쓰겠다.
const Blockchain = require('./blockchain')

//위에서 가져온 모듈의 객체를 만든다.
const bitcoin = new Blockchain();

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");

//찍어보기
console.log(bitcoin)

//결과
//Blockchain { chain: [], newTransactions: [] }


다시 실행해보자


와우. 일단 그럴듯한 객체 데이터가 생성이 된것을 볼 수 있다. 몇개를 더 만들어 볼까?

//새로운 블락 만들기
bitcoin.createNewBlock(1111,"aaaaaaa","1a1a1a1a1a1a");
bitcoin.createNewBlock(2222,"bbbbbbb","2b2b2b2b2b2b");
bitcoin.createNewBlock(3333,"ccccccc","3c3c3c3c3c3c");


결과

Blockchain {

  chain: 

   [ { index: 1,

       timestamp: 1527223987875,

       transactions: [],

       nonce: 1111,

       hash: '1a1a1a1a1a1a',

       previousBlockHash: 'aaaaaaa' },

     { index: 2,

       timestamp: 1527223987875,

       transactions: [],

       nonce: 2222,

       hash: '2b2b2b2b2b2b',

       previousBlockHash: 'bbbbbbb' },

     { index: 3,

       timestamp: 1527223987875,

       transactions: [],

       nonce: 3333,

       hash: '3c3c3c3c3c3c',

       previousBlockHash: 'ccccccc' } ],

  newTransactions: [] }


이번 포스팅에서는 새로운 블락을 생성하고 콘솔로 한번 찍어 보았다. 아직은 이게 먼지 100% 감이 안올거다. 일단 하나씩 따라와 보자. 

  1. 김도원 2018.07.07 12:38

    오타 있네요 ㅎㅎ..

    첫번 째 코드블록 주석 보시면
    //다음 거래를 위한 거래내역 배열 비워주고 새로운 블록을 chin 배열에 추가

    의 주석 중 chin 배열에 추가 인데 chain 배열에 추가 로 변경해야합니다 ~

    • 길위의 개발자 2018.07.09 17:27 신고

      감사합니다. 급하게 정리하느라 검토를 못했습니다. ㅠㅠ 요즘 일이 바빠서 블로그 정리도 못하고 있네요. 더운날씨 건강조심하시기 바랍니다.

객체의 이해


자바스크립트 객체는 프로퍼티가 키/값 쌍으로 되어 있는 만큼 해시 맵에 빗대어 생각하면 이해하기 쉽다. 객체 프로퍼티에 접근할 때는 점 표기법 또는 각괄호 표기법 중 무엇을 해도 상관없다. 프로퍼티에 값을 할당하면 언제든 객체에 새 프로퍼티를 추가 할 수 있으며 delete 연산자를 사용하면 언제든 프로퍼티를 제거할 수 있다. 프로퍼티의 존재 여부는 프로퍼티 이름과 객체를 in 연산자와 함께 사용하면 알 수 있다. 이때 고유 프로퍼티만 확인하고 싶다면 모든 객체에 대 포함되어 있는 hasOwnProperty()를 사용하면 된다. 모든 객체 프로퍼티는 기본적으로 열거 가능하다. 열거 가능하다는 말은 for-in 반복문이나 Object.keys()를 사용할 때 볼 수 있다는 뜻이다.


프로퍼티는 데이터 프로퍼티와 접근자 프로퍼티로 나누어진다. 데이터 프로퍼티는 값을 담아두기 위한 공간이므로 이 프로퍼티에서 값을 읽거나 저장할 수 있다. 데이터 프로퍼티에 함수를 담아두면 이 프로퍼티는 객체의 메소드로 취급된다. 데이터 프로퍼티와 달리 접근자 프로퍼티 자체에는 데이터를 저장할 수 없다. 접근자 프로퍼티는 게터와 세터를 조합하여 특정 동작을 수행한다. 데이터 프로퍼티와 접근자 프로퍼티 모두 객체 리터럴 표기법을 사용해 만들 수 있다.

 

모든 프로퍼티에는 관련된 내부 속성이 몇 가지 있으며 이러한 속성이 프로퍼티가 어떻게 동작하는지 결정한다. 데이터 프로퍼티와 접근자 프로퍼티에는 둘다 Enumerable Configurable 이라는 속성이 있다. 데이터 프로퍼티에는 WritableValue라는 속성이 추가로 있는 반면, 접근자 프로퍼티에는 GetSet 속성이 더 있다. 모든 프로퍼티의 EnumerableConfigurable 속성은 true가 기본 값이며 데이터 프로퍼티의 Writable 속성 역시 true가 기본 값이다. Object.defineProperty() 또는 Object.defindeProperties()를 사용하면 속성을 변경할 수 있으며 Object.getOwnPropertyDescriptor()를 사용하면 설정된 속성 값을 가져올 수 있다.

 

객체의 프로퍼티를 수정할 수 없게 만드는 방법은 세 가지가 있다. Object.preventExtensions()를 사용하면 객체에 프로퍼티를 추가할 수 없다. object.seal() 메소드를 사용하면 봉인된 객체를 만들 수 있는데 봉인된 객체는 확장 불가능해지며 객체의 프로퍼티는 설정 불가능해진다. Object.freeze()를 사용해 객체를 동결하면 객체가 봉인되는 것은 물론 데이터 프로퍼티에 값을 저장할 수도 없게 된다. 확장 불가능한 객체를 다룰 때는 잘못된 방식으로 객체에 접근했을 때 에러가 발생할 수 있도록 엄격한 모드를 사용하는 것이 좋다.

 

 

 자바스크립트의 객체는 동적이기 때문에 언제라도 바꿀 수 있다. 클래스 기반 언어는 클래스 정의에 따라 객체를 수정할 수 없도록 만들지만 자바스크립트 객체에는 이런 제약이 없다.

 

프로퍼티 정의

 

객체를 만드는 방법

1. Object 생성자를 사용하는 방법

2. 객체 리터럴 사용하는 방법

 

 

var parson 1 = { name :"kim"}

 

var person2 = new Object();

person2.name = "kim";

 

person1.age = 23

person2.age = 23

 

person1.name = "hong";

person2.name = "sim";

 

작성한 객체는 일부러 막아두지 않는 이상 언제든지 수정할 수 있다.

자바스크립트는 프로퍼티를 처음 객체에 추가할 때 객체에 있는 put 이라는 내부 메소드를 호출 한다. put 메소드는 객체에 프로퍼티 저장 공간을 생성한다. 이 동작은 수행하면 초기값은 물론 프로퍼티의 속성도 설정한다. 따라서 위의 예제에서 nameage 프로퍼티가 처음 정의 될 때마다 put 메소드가 호출된다.

 

put을 호출하면 객체에 고유프로퍼티가 만들어진다. 고유프로퍼티는 객체의 특정 인스턴스에 속해 있으며 인스턴스에 바로 저장된다.

 

기존 프로퍼티에 값을 할당 할때는 set이 호출 된다. set은 프로퍼티의 현재 값을 새 값으로 교체 한다.

 

프로퍼티 확인하기

 

잘못된 방법

 

if(person1.age){

 

}


 ****

이 방식의 문제점은 자바스크립트 타입 강제변환이 결과에 영향을 끼친다는 것이다. if 조건문은 주어진 값이 참스러운 값 (객체, 비어있지 않은 문자열, 0이 아닌 숫자, true) 이면 true로 취급하고 거짓스러운 값(null,undefined, false, NaN, 빈문자열) 이면 false로 취급한다. 객체 프로 퍼티에 거짓스러운 값이 저장될 수 있기 때문에 예제 코드와 같은 방식은 잘못 실행될 수 있다.

 

in 연산자 사용

in연산자는 특정 객체에 주어진 이름의 프로퍼티가 존재하는지 확인하고 존재하면 true를 반환한다. 사실 in연산자는 해시테이블에 주어진 키가 있는지 확인한다.

 

)

console.log("name" in person1) //true

consloe.log("age" in person1) //true

consloe.log("hobby" in person1) //false

 

 

자바스크립트에서 메소드는 함수를 참조하고 있는 프로퍼티이므로 메소드의 존재여부도 같은 방식으로 확인할 수 있다.

 

var person1 = {

name: "kim",

sayName: function(){

console.log(this.name)

}

 

}

 

console.log("sayName" in person1); // true

 


때로는 프로퍼티의 존재 여부를 확인하는 것에 그치지 않고 해당프로퍼티가 객체의 고유 프로퍼티인지도 확인해야 한다. in 연산자는 고유프로퍼티와 프로토타입 프로퍼티 둘다 찾기 때문에 고유 프로퍼티인지 확인하고 싶다면 다른 방법을 동원해야 한다. 모든 객체에 포함되어 있는 hasOwnProperty() 메소드는 주어진 프로퍼티가 객체에 존재하는 동시에 고유 프로퍼티일 때만 true를 반환한다.

 

var person1 = {

name: "kim",

sayName: function(){

console.log(this.name)

}

 

}

 

console.log("name" in person1); // true

console.log("person1.hasOwnProperty("name")); // true

 

console.log("toString" in person1); // true

console.log("person1.hasOwnProperty("toString")); // false

 

nameperson1의 고유 프로퍼티이므로 in 연산자와 hasOwnProperty()는 둘다 true를 반환한다. 하지만 toString() 메소드는 모든 객체에 포함되어 있는 프로토타입 프로퍼티이므로 in 연산자는 true를 반환하지만 hasOwnProperty()false를 반환한다.

 

프로퍼티 제거

프로퍼티 값을 null로 바꾸는 것만으로 프로퍼티가 객체에서 환전히 제거 되지 않는다. 값을 null로 바꾸는 동작은 set 내부 메소드를 null과 함께 실행하므로 앞에서 보았듯 프로퍼티의 값만 달라지게 된다.

객체에서 프로퍼티를 완전히 제거할 때는 delete 연산자를 사용해야 한다.

 

객체프로퍼티에서 delete 연산자를 사용하면 내부적으로 delete가 호출된다. 무사히 실행을 마쳤을 때 true를 반환한다.

 

 

var person1 = {

name: "kim",

sayName: function(){

console.log(this.name)

}

 

}

 

console.log("name" in person1) //true

 

delete person1.name;

console.log("name" in person1); //false

console.log(person1.name) //undefined

 

존재하지 않는 프로퍼티에 접근하면 undefinde가 반환된다

 

 

열거

객체에 추가하는 프로퍼티는 기본적으로 열거가 가능하다.

for- in 문을 사용해서 훑을 수 있다. 열거 가능 프로퍼티에는 Enumerable 이라는 내부속성이 true로 설정되어 있다.

 

var property;

for(property in object){

console.log("이름" + property);

console.log("" + object[property]);

}

 

 

객체 프로퍼티의 목록을 가져와야 한다면 ECMAScript 5에서 도입된 Object.keys()메소드가 유용하다.

 

var properties = Object.keys(object);

var I, len;

 

for(i=0, len=properties.length; i<len; i++){

console.log("name" + properties[i]);

console.log("value" + object[properties[i]]);

 

}

 

일반적으로 프로퍼티 이름 목록을 배열 형태로 다루고 싶을때는 Object.keys()를 사용하고 굳이 배열이 필요 없을 때는 for-in을 사용한다. for-in 반복문에서는 열거 가능한 프로토타입 프로퍼티도 반환하지만, object.keys()는 고유 프로퍼티만 반환한다.

 

모든 프로퍼티를 열거할 수 있는 것은 아니다. 객체의 네이티브 메소드는 대부분 Enumerable 속성이 false로 되어 있다. 특정 프로퍼티가 열거 가능한지 확인할 때는 propertyIsEnumerable() 메소드를 사용하면 된다. 이 메소드는 모든 객체에 포함되어 있다.

 

var person1 = {

name: "kim"

 

}

 

console.log("name" in person1) //true

console.log(person1.propertyIsEnumerable("name")); //true

 

var properties = Object.keys(person1);

 

console.log("length" in properties); // true

console.log(properties.propertyIsEnumerable("length")) //false

 

nameperson1에 직접 추가한 프로퍼티이므로 열거 가능하다. 반면 properties 배열의 length 프로퍼티는 Array.prototype의 내장 프로퍼티이므로 열거 가능하지 않다. 네이티브 프로퍼티는 대부분 기본적으로 열거 가능하지 않다.

 

프로퍼티 종류

1.데이터 프로퍼티 : 값을 포함하고 있다. put 메소드의 기본 동작을 통해 생성 된다.

2.접근자 프로퍼티: 값을 포함하지 않는 대신 프로퍼티를 읽었을 때 호출할 함수 게터(getter)와 값을 설정할 때 호추할 함수 세터(setter)를 정의 한다.


)

var person1 = {

name: "kim",

 

get name(){

console.log("name 읽는 중“);

return this.name;

},

 

set name(value){

 

console.log("name의 값을 %s로 설정하는 중", value);

this.name = value;

}

 

};

console.log(person1.name); //name 읽는 중 kim 출력

 

person1.name = "hong";

console.log(person1.name) //name의 값을 hong으로 설정하는 중 출력후 hong

 

이 예제는 name이라는 접근자 프로퍼티를 정의하고 있다. 접근자 프로퍼티에서 사용할 실제 값은 _name이라는 데이터 프로퍼티에 저장한다. name의 게터와 세터를 정의할 때는 function 키워드가 없다는 점만 제외하면 함수를 정의하는 문법과 비슷하다. get 또는 set이라는 특수한 키워드를 접근자 프로퍼티 이름앞에 사용하고 이름 뒤에는 괄호와 함수 코드를 입력한다. 게터는 값을 반환해야 하고 세터는 프로퍼티에 할당할 값을 인수로 전달 받을 수 있어야 한다.

 

프로퍼티 속성


공통속성

데이터 프로퍼티와 접근자 프로퍼티의 공통속성은 두가지다.

하나는 Enumerable 인데 프로퍼티가 열거 가능한지 정하는 속성이고 다른 하나는 Configurable로서 프로퍼티를 변경할 수 있는지 정하는 속성이다. Configurable 속성이 있는 설정가능 프로퍼티는 delete 연산자를 사용해 언제든 제거할 수 있고 속성도 언제든 변경할 수 있다. 다시 말해 설정 가능 프로퍼티는 데이터 프로퍼티를 접근자 프로퍼티로 바꾸거나 그 반대로 바꾸는 것도 가능하다. 객체의 모든 프로퍼티는 따로 설정을 하지 않는 한 열거 가능하며 설정 가능하다.

 

객체의 속성을 바꾸고 싶을 때는 object.defineProperty()메소드를 사용할 수 있다. Object.defineProperty() 메소드에는 인수를 세 개 전달하는 데 첫 번재 인수는 프로퍼티를 소유하고 있는 객체 이고 두 번째 인수는 프로퍼티 이름, 세 번째 인수는 설정할 프로퍼티 속성 값을 포함하고 있는 프로퍼티 서술자 객체이다.

 

var person1 = {name:"kim"}

//열거 불가능

Object.defineProperty(person1,"name",{

enumerable:false});

 

console.log("name" in person1); //true

console.log(person1.propertyIsEnumerable("name")); //false

 

var properties = Object.keys(person1);

console.log(properties.length) // 0

 

//설정불가능

Object.defineProperty(person1,"name",{

configurable:false

});

 

//

delete person1.name;

console.log("name" in person1); //true

console.log(person1.name); //kim

 

//에러

Object.defineProperty(person1,"name",{

configurable:true

});

 

 

데이터 프로퍼티 속성

1. value:

2. writable: 프로퍼티에 값을 저장할 수 있는지 정의하는 불리언 값

 

var person1 ={name : "kim"}


두개는 같다


var person1 = {};

Object.defineProperty(person1,"name",{

value: "kim",

enumerable:true,

configurable:true,

writable:true

 

});

 

Object.defineProperty()를 실행하면 먼저 해당 프로퍼티가 있는지 확인한다. 프로퍼티가 없다면 새 프로퍼티를 추가하고 프로퍼티 서술 객체에 정의한 대로 속성을 설정한다. 이 예제에서 nameperson1의 프로퍼티가 아니었기 때문에 새로 작성된다.

Object.defineProperty()를 사용해 새 프로퍼티를 정의할 때 서술자에 없는 속성은 모두 false로 설정된다. 따라서 필요한 속성은 반드시 서술자에 포함시켜 두어야 한다.


다음 예제는 Object.defineProperty()를 호출할 때 명시적으로 true라고 설정한 속성이 없었기 때문에 열거 불가능, 설정불가능, 쓰기 불가능한 name 프로퍼티를 만든다.

 

 

var person1 = {};

 

Object.defineProperty(person1,"name",{

value: "kim"

});

 

console.log("name" in person1); //true

console.log(person1.propertyIsEnumerable("name")); //false

 

delete person1.name;

console.log("name" in person1); //true

 

person1.name = "hong";

console.log(person1.name); //kim

 

접근자 프로퍼티 속성


접근자 프로퍼티는 저장할 값이 필요 없으므로 valuewritable 속성은 필요 없다

대신 setget 속성이 필요하다.

 

접근자 프로퍼티를 정의할 때 객체 리터럴 형식 대신 접근자 프로퍼티 속성을 사용하면 기존에 있던 객체에도 프로퍼티를 추가할 수 있다는 장점이 있다.

 

var person 1 ={_name:"kim",

 

get name(){

console.log("name 읽는 중")

return this._name;

},

set name(value){

console.log("name의 값을 %s로 설정하는중",value);

this._name=value;

}

 

}

 

이 코드는 다음과 같이 작성할 수 있다.

 

var person1= {_name:"kim"};

 

Object.defineProperty(person1,"name",{

get:function(){

console.log("name 읽는 중")

return this._name;

},

set:function(value){

console.log("name의 값을 %s로 설정하는중",value);

this._name=value;

 

},

enumerable:true,

configurable:true

});

 

Object.defineProperty()에 전달된 객체에 있는 get키와 set키는 값이 함수인 데이터 프로퍼티이다. 이 객체에서는 객체 리터럴 형태의 접근자를 사용할 수 없다.

접근자 프로퍼티에도 enumerable 이나 configurable 과 같은 속성을 설정하여 프로퍼티의 작동 방식을 조정할 수 있다. 설정안하면 false 가 설정된다.

 

여러프로퍼티 정의하기

Object.defineProperty() 대신 Object.defineProperties()를 사용하면 동시에 여러 프로퍼티를 설정할 수 있다. 이 메소드에는 인수를 두 개 전달한다. 첫 번째 인수는 대상 객체이고, 두 번째 인수는 정의할 프로퍼티의 정보를 담고 있는 객체이다.

 

var person1 = {};


Object.defineProperties(person1,{

 

//데이터를 정의할 데이터 프로퍼티

_name : {

value: "kim",

enumerable:true,

configurable:true,

writable:true

},

//접근자 프로퍼티

 

name :{

get:function(){

console.log("name 읽는 중");

return this._name;

},

set:function(value){

console.log("name의 값을 %s로 설정하는중",value);

this._name=value;

},

 

enumerable:true,

configurable:true

 

}

 

})

 

프로퍼티 속성 가져오기

Object.getOwnPropertyDescriptor() 메소드 사용

고유프로퍼티만 사용가능

첫 번째 인수: 대상객체

두 번째 인수: 정보를 가져올 프로퍼티의 이름

인수로 이름을 전달한 프로퍼티가 존재하면 프로퍼티의 속성 정보를 포함한 객체가 반환되며, 이 객체에는 configurable, enumerable을 비롯한 네 종류의 키가 설정되어 있다.

 

var person1 = {

name:"kim"

};

 

var descriptor = Object.getOwnPropertyDescriptor(person1,"name");

 

console.log(descriptor.enumerable); //true

console.log(descriptor.configurable); //true

console.log(descriptor.writable); //true

console.log(descriptor.vlaue); //kim

 

 도서: 객체지향 자바스크립트의 원리 정리

 

원시타입과 참조타입


자바스크립트에서는 원시 타입(primitive type) 참조 타입(reference type)이라는 두 가지 자료형을 제공한다.

숫자, 불린값, null과 undefined는 원시 타입이다. 객체, 배열, 함수는 참조 타입이다.

원시 타입 데이터는 변수에 할당될 때 메모리 상에 고정된 크기로 저장되고 해당 변수가 원시 데이터 값을 보관한다.

참조 타입 데이터는 크기가 정해져 있지 않고 변수에 할당될 때 값이 직접 해당 변수에 저장될 수 없으며, 변수에는 데이터에 대한 참조만 저장된다. 참조는 참조 타입 데이터의 주소이지 해당 데이터의 값이 아니다.

원시 타입 변수 복사

각 변수 간에 원시 타입 데이터를 복사할 경우 데이터의 값이 복사된다. 다음 예제를 보자.

var x = 100;        // 원시 타입 데이터를 선언
var y = x;          // 값을 새 변수에 복사
x = 99;             // 'x'의 값을 변경
console.log(y);     // 100, 'y'의 값은 변경되지 않음

참조 타입 변수 복사

각 변수 간에 참조 타입 데이터를 복사할 경우 데이터의 참조가 복사된다. 다음 예제를 보자.

var x = {count: 100};   // 참조 타입 데이터를 선언
var y = x;              // 참조를 새 변수에 복사
x.count=99;             // 참조 타입 데이터를 변경
console.log(y.count);   // 99, 'x'와 'y'는 동일한 참조를 담고 있으며, 따라서 동일한 객체를 가리킴


참조:http://codingnuri.com/javascript-tutorial/javascript-primitive-types-and-reference-types.html


자바스크립트에서 데이터 대부분은 객체이거나 객체를 통해 접근하는 값이다. 자바스크립트는 함수조차 객체로 표현하며 덕분에 자바스크립트의 함수는 일급함수이다.

원시타입과 참조타입: 두 타입모두 객체를 통해서 접근하지만 서로 다르게 동작하므로 차이점을 익혀두는게 좋다.

 

타입이란?

자바스크립트에 클래스라는 개념은 엇지만 이를 대체할 타입이라는 개념이 존재하며 타입은 크게 두 종류로 구분한다.

1.원시타입: 단순한 데이터를 저장하는 원시타입

2.참조타입: 객체로 저장되고 메모리 상의 주소를 가리킨다.

 

원시타입은 스택에 저장하고 참조는 힙에 저장하여 원시타입과 참조 타입을 구분하고 있지만 자바스크립트는 그렇지 않다. 자바스크립트에서는 변수 객체의 스코프를 따라 변수를 추적한다. 원시타입의 원시값은 변수 객체에 저장되지만 참조타입에서 변수 객체에 저장되는 참조 값은 메모리에 있는 실제 객체를 가리키는 포인터이다.

 

원시타입종류

Boolean

Number

String

Null

Undefied

 

모든 원시타입에는 값을 표현하는 리터럴 형식이 있다. 리터럴 이란 코드에 직접 입력된 이름이나 가격처럼 변수에 저장되지 않은 값을 의미한다.

 

var name = "kim";

var count = 23;

var found = true;

 

원시 값을 변수에 할당하면 값이 변수로 복사된다.

 

var a = "red";

var b = a;    //red

 

a,b는 같은 값을 가지고 있지만 두 값은 완전히 별개의 값이며 b에 아무런 영향을 주지 않고 a의 값을 바꿀 수 있다. 이는 두 값이 각 값당 하나씩 할당된 서로 다른 영역에 저장되어 있기 때문이다.

원시 값을 가지고 있는 각 변수는 독립된 저장 공간을 사용하기 때문에 다른 변수의 값을 바꿔도 영향을 받지 않는다.

 

var a = 'red';

var b = a;

console.log(a); //red

console.log(b); //red

 

a = 'blue';

console.log(a) // blue;

console.log(b) // red;

 

원시타입 종류 확인

type of 연산자로 확인

type of 연산자를 변수에 사용하면 변수에 저장된 데이터의 타입을 문자열로 반환한다.

 

참고 null 인지 아닌지 판단할 때

console.log(value === null);

 

등호 두 개를 사용하면 비교를 수행하기 전에 형변환을 하기 때문에 문자 ‘5’ 5는 같다. 등호 세 개를 이용하면 비교하지 않고 바로 비교를 한다.

 

원시메소드

원시타입인 문자열 숫자 불리언에는 사실 메소드가 존재한다.

var name = 'kang';

var lastname = name.toLowerCase();

 

원시 값에도 메소드가 존재하지만 원시 값 자체는 객체가 아니다. 자바스크립트의 원시 값은 다른 다른 언어와 유사한 경험을 주기 위해 마치 객체처럼 다룰 수 있게 되어있다.

 

참조타입

참조타입은 자바스크립트 객체를 나타내며 클래스가 없는 자바스크립트라는 언어에서 클래스와 가장 가까운 개념이다. 참조 값은 참조 타입의 인스턴스이며 객체와 같은 말이다. 객체는 순서가 없는 프로퍼티로 이루어져 있으며 프로퍼티는 이름과 값으로 구성되어 있다. 프로퍼티의 값이 함수 일 때 이 프로퍼티를 가르켜 메소드라고 부른다. 프로퍼티나 메소드를 다루려면 먼저 객체를 만들어야 한다.

 

객체 생성

객체를 만드는 것을 가리켜 인스턴스화 한다고 하는데, 자바스크립트에서 인스턴스화 방법은 두가지가 있다.


1. new 연산자와 생성자를 사용하는 것이다

생성자는 사실 new 연산자와 함께 사용하여 객체를 만들 수 있는 함수일 뿐이다. 관례상 자바스크립트에서 생성자의 이름은 첫 글자를 대문자로 시작하여 생성자가 아닌 다른 함수와 구분하고 있다.

참조 타입은 할당된 변수에 값을 직접 저장하지 않으므로 이 예제에서 object 변수에 저장된 값은 사실 객체 인스턴스가 아니라 객체가 있는 메모리상의 위치를 가리키는 포인터이다. 이것이 바로 원시 값과 객체의 가장큰 차이점인데, 원시값은 변수에 직접 값 자체가 저장된다. 객체를 변수에 할당하는 일은 사실 객체의 포인터를 할당하는 셈이다. 다시말해 어떤 변수를 다른 변수에 할당하면 두 변수는 모두 포인터의 복사본만 저장하고 있으므로 메모리상에서 똑같은 객체를 참조하게 된다.


) var object1 = new Object();

var object2 = object1;

 


객체 참조 제거

) var object1 = new Object();

object1 = null;

 

 

프로퍼티 추가 및 제거

자바스크립트의 특징 중 하나는 언제든 프로퍼티를 추가하고 삭제할 수 있다.

 

) var object1 = new Object();

var object2 = object1;

 

object1.hi = "hello";

console.log(object2.hi); //hello


object1object2는 같은 객체를 가리키고 있으므로 이 프로퍼티는 object2에서도 접근 할 수 있다.

 

내장타입 인스턴스화

 

Array 숫자 인텍스 값을 가진 순차 목록

Date 날짜와 시간

Error 실행 중 발생하는 에러

Function 함수

Object 일반적인 객체

RegExp 정규표현식

 

내장 참조 타입은 다음과 같이 new 연산자를 사용해 인스턴스로 만들 수 있다.

 

리터럴 형식

리터럴은 new 연산자와 객체의 생성자를 사용하여 명시적으로 객체를 만들지 않고도 참조 값을 만들 수 있는 문법이다.

 

객체 및 배열 리터럴

프로퍼티가 두 개 있는 객체 예)

var book = {name:"자바스크립트의 원리",

year: 2016

}

 

아래와 같다.


var book = new Object();

book.name = "객체지향";

book.year = 2014;


참고

객체 리터럴을 사용하면 실제로도 new Object()를 호출하지 않는다. 실제로 생성자를 호출하지 않지만 자바스크립트가 내부적으로 new Object()를 사용했을 때와 동일한 단계를 수행한다.

 

 

배열리터럴

var colors = ["red","blue","green"];

console.log(colors[0]); //red

 

이 코드는 다음과 같다.

 

var colors = new Array("red","blue","green")

console.log(colors[0])

 

함수리터럴

function reflect(value){

return value;

}

 

// 위코드는 다음과 같다.

var reflect = new Function ("value","return value");

 

이처럼 간단한 함수일때도 생성자를 사용하는 방법보다 리터럴을 사용하는 방법이 작성하기도 편하고 이해하기도 쉽다. 게다가 생성자 형태로 작성한 함수는 디버그하기 까다롭다. 자바스크립트 디버거는 생성자를 통해 작성된 함수를 인식하지 못하므로 이렇게 작성된 함수는 들여댜 볼 수 없다.

 

정규표현식 리터럴

var numbers = |\d+|g;

var numbers = new RegExp("||d", "g");


프로퍼티 접근

var array = [];

array.push(12345);

 

각괄호 표기법을 사용할 때는 다음과 같이 각괄호 안에 메소드 이름을 문자열로 입력한다.

 

var array = [];

array["push"](12345);

 

이 문법은 접근할 프로퍼티를 동적으로 정해야 할 때 유용하다.

 

var array = [];

var method = "push";

array[method](1234);

 

참조타입 확인 

instanceof 연산자 사용

 

var items = [];

var object = {};

 

function reflect(value){

return value;

}

 

console.log(items instanceof Array); //true

console.log(object instanceof Object);

 

-자바스크립트에서 모든 참조 타입은 object를 상속하므로 사실 모든 객체는 object의 인스턴스다.

 

배열확인

var items = [];

console.log(Array.isArray(items)); //true

 

참고:explore8이하에서는 지원 안됨


원시래퍼타입

 

var name = "kim";

var firstChar = name.charAt(0);

console.log(firstChar) //"k"

 

이때 내부에서 일어나는 일은 다음과 같다.

 

var name = "kim";

var temp = new String(name);

var firstChar = name.charAt(0);

temp = null;

console.log(firstChar) //"k"

 

두 번째 줄에서 원시 문자열을 객체처럼 취급했기 때문에 자바스크립트 엔진은 charAt(0)이 정상 적으로 작동하도록 String의 인스턴스를 만든다. 이렇게 작성한 String 객체는 한 문장만 실행하고 곧 다시 파괴되는데 이 과정을 가리켜 오토박싱이라고 한다. 일반적인 객체를 다루듯 문자열에 프로퍼티를 추가해보면 이를 확인 할 수 있다.

 

var name = "kim";

name.last = "tong";

console.log(name.last); //undefind

 

평범한 객체를 다룰 때는 언제든 프로퍼티를 추가할 수 있으며 추가된 프로퍼티는 일부러 제거하지 않는 한 추가된 상태 그대로 있다. 원시 값에 프로퍼티를 추가하려고 하면 원시 래퍼 타입이 임시로 만들어 지고 이 객체에 프로퍼티가 추가된다. 하지만 임시로 만들어진 원시 래퍼타입은 곧 파괴 되기 때문에 프로퍼티가 사라진 것처럼 보인다.

 

//실제로 자바스크립트 엔진이 하는 일

var name = "kim";

var temp = new String(name);

temp.last = "tong";

temp = null;

 

var temp = new String(name);

console.log(temp.last); //undefind

temp = null;

 

var name = "kim";

var count = 10;

var found = false;

 

console.log(name instanceof String); //false

console.log(count instanceof Number); //false

console.log(found instanceof Boolean); //false

 

임시 객체는 값을 읽을 때 만들어지기 때문에 instanceof 연산자는 false를 반환한다. instanceof 연산자가 실제로는 아무런 값도 읽지 않기 때문에 임시 객체도 만들어지지 않고 따라서 원시 값은 원시 래퍼 타입의 인스턴스가 아니라는 결과가 반환되는 것이다. 원시 래퍼 타입을 명시적으로 사용해 값을 생성하는 방법도 있지만 이때는 다른 문제가 발생한다.

 

var name = new String("kim");

var count = new Number(10);

var found = new Boolean(false);

 

console.log(typeof name);

console.log(typeof count);

console.log(typeof found);

//보다시피 원시 래퍼타입의 인스턴스를 만들면 객체가 만들어지기 때문에 typeof연산자를 사용한 결과는 의도한 것과 다르게 나타난다.

 

 

요약

자바스크립트에는 클래스가 없는 대신 타입이 존재한다. 각 변수나 데이터에는 그에 해당하는 특수한 원시 타입 또는 참조 타입이 존재한다. 다섯 가지 원시 타입은 주어진 컨텍스트 내에서 변수 객체에 바로 저장되는 단순한 값을 의미 한다.

typeof 연산자를 사용하면 원시타입의 종류를 확인할 수 있다.

하지만 nullnull은 비교해야 한다.

참조 타입은 클래스가 없는 자바스크립트에서 클래스와 가장 가까운 개념이며 객체는 참조 타입의 인스턴스다. new 연산자나 리터럴 형식을 사용하면 새로운 객체를 생성할 수 있다. 프로퍼티와 메소드에 접근할 때는 보통 점 표기 법을 사용하는데 각괄호 표기법을 대신 사용할 수도 있다. 자바스크립트에서는 함수도 객체이며, 어떤 값이 함수인지는 typeof 연산자를 사용해 확인할 수 있다. instanaceof 연산자는 주어진 객체가 어떤 참조 타입의 인스턴스인지 확인할 때 사용한다.

 

자바스크립트에는 String, Number, Boolean이라는 세 종류의 원시 래퍼 타입이 있어 원시 값을 마치 참조 값처럼 다룰 수 있도록 해주지만, 자동으로 생성한 임시 객체는 문장 하나를 완료하자마자 곧 파괴 된다. 원시 래퍼 타입의 인스턴스를 명시적으로 만들수도 있지만 이 방법은 혼란을 이야기할 소지가 있어 권장하지 않는다.

 

도서 객체지향 자바스크립트의 원리 정리

*자바스크립트 뒤로가기 쿼리


<div align="center">


<button onclick="goBack()" class="btn btn-primary" style='color: white; background-color:rgb( 59, 89, 152);'>뒤로가기</button>


</div>



<script>

function goBack() {

    window.history.back();

}

</script>




*서버에서 auth 객체를 view 에 던져서 존재하면 페이지를 보여주고

없으면 location.href로 바로 페이지 강제 이동


<% if(auth==null||auth==""||auth===null){ %>

<script>

location.href='https://000000.00000.00000';

</script>

<% } %>



                

동적쿼리 생성

 output += '<a href="#" class="list-group-item"><img src="http://www.icons101.com/icons/2/facebook_ui_icons_vector_by_lopagof/128/list.png"; onclick="image(\'' + rows2[i].replyer + '\');" width="25" height="auto" class="img-responsive">';



<script>

function image(a){

       //var a =$('#color').text();

       alert(a) 

</script>    

    

}


문제는 음...

동적쿼리를 생성하고 ...

ajax로 값을 받아와서 동적 쿼리에 넣어 그 값을 함수에 던져준다...

숫자는 잘들어가지는데 문자를 던지니깐 계속 에러가 났다.

출력해보니..... undefind 하면서 정의 할 수 없다고.. 

3시간 넘게 삽질했다..


그래서 구글링!!!

인자 사이에 \'' 요런걸 넣어라네.....

갈길이 멀다.ㅠㅠ



*참고

accepted

You need to wrap the input item.store_code with quotation marks; otherwise, it tries to treat it as a variable, not a string:

html += '<div class="col-sm-3"><input type="button" onclick="noActivationCodeRegistration(\'' + item.store_code + '\');" value="This Is My Store" data-store-code="' + item.store_code + '"></div>';


1.

<HTML>

<HEAD>

<TITLE> hamsoo</TITLE>

</HEAD>

<script>


//함수는 객체다

//함수 func는 function이라는 객체의 인스턴스다.

//따라서 func는 function이 가지고 있는 메소드들을 상속한다.

function func(){

}

func();




// 함수를 호출 하는 다른 방법

//함수 sum은 Function 객체의 인스턴스다. 그렇기 때문에 객체 Function의 메소드 apply를 호출 할수 있다. 

function sum(arg1, arg2){

    return arg1+arg2;

}

alert(sum.apply(null, [1,2]))


</script>

<BODY>


</BODY>

</HTML>




2.

<HTML>

<HEAD>

<TITLE> hamsoo</TITLE>

</HEAD>

<script>


o1 = {val1:1, val2:2, val3:3}

o2 = {v1:10, v2:50, v3:100, v4:25}


function sum(){


    var _sum = 0;

    for(name in this){

        _sum += this[name];

    }

    return _sum;

}



alert(sum.apply(o1)) // 6

alert(sum.apply(o2)) // 185



//sum.apply(o1)은 함수 sum을 객체 o1의 메소드로 만들고 sum을 호출한 후에 sum을 삭제한다. 

//sum의 o1 소속의 메소드가 된다는 것은 이렇게 바꿔 말할 수 있다.

// 함수 sum에서 this의 값이 전역객체가 아니라 o1이 된다는 의미다.

// 일반적인 객체지향 언어에서는 하나의 객체에 소속된 함수는 그 객체의 소유물이 된다. 

//하지만 JavaScript에서 함수는 독립적인 객체로서 존재하고, apply나 call 메소드를 통해서 다른 객체의 소유물인 것처럼 실행할 수 있다. 


</script>

<BODY>


</BODY>

</HTML>




1.

<!DOCTYPE html>

<html>

<head>

    <title>hamsoo</title>

</head>



<script>

//함수에는 arguments 라는 변수에 담긴 숨겨진 유사배열이 있다.

//arguments.length를 이용해서 함수로 전달된 인자의 개수를 알아낼 수도 있다.

//이러한 특성에 반복문을 결합하면 함수로 전달된 인자의 값을 순차적으로 가져올 수 있다.

function sum(){

    var i, _sum = 0;    

    for(i = 0; i < arguments.length; i++){

        document.write(i+' : '+arguments[i]+'<br />');

        _sum += arguments[i];

    }   

    return _sum;

}

document.write('result : ' + sum(1,2,3,4));


</script>



   </body>

</html>



2.

<!DOCTYPE html>

<html>

<head>

    <title>hamsoo</title>

</head>



<script>

//매개변수와 관련된 두가지 수가 있다.

// 하나는 함수.length

// 하나는 arguments.length


function zero(){

    console.log(

        'zero.length', zero.length,

        'arguments', arguments.length

    );

}

function one(arg1){

    console.log(

        'one.length', one.length,

        'arguments', arguments.length

    );

}

function two(arg1, arg2){

    console.log(

        'two.length', two.length,

        'arguments', arguments.length

    );

}


zero(); // zero.length 0 arguments 0 

one('val1', 'val2');  // one.length 1 arguments 2 

two('val1');  // two.length 2 arguments 1

</script>




   </body>

</html>




+ Recent posts