__My_Notes

————————————————————-

1.Javacript

————————————————————-

Useful JavaScript Array Methods

1.Array.of :

const numbers = Array.of(5);
const numbers = Array.of(5, 6, 7, 8);

// console.log(numbers) [5]
// console.log(numbers) [5,6,7,8]

2.Array.from :


const numbers = [1, 2, 3, 4, 5];
// Following code will create an array where each element is multiplied by 2
const copy = Array.from(numbers, value => value * 2);
console.log(copy); // [2, 4, 6, 8, 10]

3.Array.find :


const employees = [
 { name: "David Carlson", age: 30 },
 { name: "John Cena", age: 34 },
 { name: "Mike Sheridan", age: 25 },
 { name: "John Carte", age: 50 }
];

  • and we want to get the employee record whose name is John. In this case, we can use array.find method


const employee = employees.find(employee =>        employee.name.indexOf("John") > -1);
console.log(employee); // { name: "John Cena", age: 34 }

// {name: "John Cena", age: 34}

4.Array.findIndex :


const employees = [
 { name: "David Carlson", age: 30 },
 { name: "John Cena", age: 34 },
 { name: "Mike Sheridan", age: 25 },
 { name: "John Carte", age: 50 }
];

const index = employees.findIndex(employee => employee.name.indexOf("John") > -1);
console.log(index); // 1

5.Array.filter :


const employees = [
{ name: "David Carlson", age: 30 },
{ name: "John Cena", age: 34 },
{ name: "Mike Sheridan", age: 25 },
{ name: "John Carte", age: 50 }
];
const employee = employees.filter(employee => employee.name.indexOf("John") > -1);
console.log(employee); // [ { name: "John Cena", age: 34 }, { name: "John Carte", age: 50 }]

6.Array.fill :


const checkboxes = new Array(5).fill(false);
console.log(checkboxes);
// [false, false, false, false, false]

7.Array.forEach :


const months = ["January", "February", "March", "April"];
const returnedValue = months.forEach(month => {
 console.log(month);
 return month;
});
console.log('returnedValue: ', returnedValue); // undefined


8.Array.map :


const months = ["January", "February", "March", "April"];
const transformedArray = months.map(month => month.toUpperCase());
console.log(transformedArray); // ["JANUARY", "FEBRUARY", "MARCH", "APRIL"]


9.Array.every :

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>

<body>
  <form class="container" id="registration_form" action="#" autocomplete="off">
    <div class="form-heading">Registration Form</div>
    <p>Open Console to see the output</p>
    <div class="form-group">
      <label for="first_name">First Name</label>
      <input type="text" class="form-control" id="first_name" placeholder="Enter first name">
    </div>
    <div class="form-group">
      <label for="last_name">Last Name</label>
      <input type="text" class="form-control" id="last_name" placeholder="Enter last name">
    </div>
    <div class="form-group">
      <label for="email">Email address</label>
      <input type="email" class="form-control" id="email" aria-describedby="emailHelp" placeholder="Enter email">
    </div>
    <div class="form-group">
      <label for="city">City</label>
      <input type="text" class="form-control" id="city" placeholder="Enter city">
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
  </form>
</body>

</html>



window.onload = function() {
 const form = document.getElementById("registration_form");
 form.addEventListener('submit', function(event) {
   event.preventDefault();
   const fields = ["first_name", "last_name", "email", "city"];
   const allFieldsEntered = fields.every(function(fieldId) {
     return document.getElementById(fieldId).value.trim() !== "";
   });
   if(allFieldsEntered) {
     console.log('All the fields are entered');
    // All the field values are entered, submit the form
   } else {
     alert("Please, fill out all the field values.");
   }
 });
};


10.Array.some :

const employees = [
  { name: "David Carlson", age: 30 },
  { name: "John Cena", age: 34 },
  { name: "Mike Sheridon", age: 25 },
  { name: "John Carte", age: 50 }
];

let indexValue = -1;
const employee = employees.some( (employee, index) => {
  const isFound = employee.name.indexOf('John') > -1;
  if(isFound) {
    indexValue = index;  
  }
  return isFound;
});
console.log(employee, indexValue);
// true 1


  1. Array.reduce :


const coordinates = [
  { x: 1, y: 2 }, 
  { x: 2, y: 3 }, 
  { x: 3, y: 4 }
];
const sum = coordinates.reduce(function (accumulator, currentValue) {
    return accumulator + currentValue.x;
}, 0);

console.log(sum); // 6


Object.assign()

ES6

  • Object.assign(target, …sources)


// 1 번째 예제

var obj = {a:1};
var copy = Object.assign({}, obj);
console.log(copy); // {a: 1}

// 2번째 예제

var obj1 = {a:1};
var obj2 = {b:1};
var obj3 = {c:1};
var obj4 = {d:1};


var newObj = Object.assign({}, obj1, obj2, obj3,obj4);


console.log(newObj); // {a: 1, b: 1, c: 1, d: 1}

// 3번째 예제 


const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);  // assign 을 한후 target의 값이 바뀌었다.  
// expected output: Object { a: 1, b: 4, c: 5 }

console.log(returnedTarget); // 이중 값이 둘어오면 나중에 값으로 cover 된다. 

// expected output: Object { a: 1, b: 4, c: 5 }



함수 생성하는 방법

  • 함수 선언식 과 표현식의 차이점

  • 함수 선언식은 호이스팅이 되고 표현식은 호이스팅이 되지 않는다.

  • 함수 선언식에서는 ; 사용하지 않는다. 표현식에서는 세미콜론 사용,

  • 선언식



greet();
// 함수 선언
function greet(){
    console.log('hi')
}


  • 표현식

const sayHello = function(){ 

  console.log('hello') 
  
  };


# 상속과 다형성의 차이점

  • 상속과 다형성은 서로 보는관점이 다르다.

    • 상위객체가 하위객체를 자기의 어떠함으로 만들어낼때 다형성이 된다.

    • 하위객체가 상위객체를 볼때 상속이 된다.

# Deep copy & Shallow copy

  • 1.Deep copy

  • 원시타입(primitive type)

  • String,Boolean,Number

    복사가 일어날때 독립적이다 새로운 메모리 공간을 확보하여 값을 저장한다.

  • Shallow copy

  • 참조 타입(reference type)

  • Object,Array,function

    복사가 일어날때, 객체 그 자체가 아닌 객체의 위치 값을 저장 한마디로 딥 카피를 하면 엄청 메모리가 많이 잡힌다. 똑같은값쓰는데 메모리값또할당받아서 쓰지말라는 것이다.

  • 예제

var x = 2;
var y = x; 
y = 3;

x // 2 

// 
// y = x 로 할당 하여도 x 값은 변하지 않는다 왜냐하면 메모리를 따로 저장하기 때문이다. 


var x = { foo: 3 };
var y = x;
y.foo = 2;

// x.foo = 2  가 된다. 
// y.foo = 2 로 바꿨다. 그런데 x.foo 값이 바뀌었다. 
// 왜냐하면 x 와 y 는 같은 메모리를 사용하기 때문이다. 위치만 따로 쓴다. 

var x = { foo: 3 };
var y = x;
y = 2;

// x.foo = 3. 
// 이것은 바뀌지 않는다. 왜냐하면 y = x 로 하여 deep Copy 가 일어나서 메모리를 따로 쓰기 때문에 x.foo 에 영향을 주지 않는다. 




var myArray = [2, 3, 4, 5];
var ourArray = myArray;
ourArray = [];

myArray // [2, 3, 4, 5]

// ourArray = [] 배열을 초기화 해도 myArray 에 영향을 주지 않는다. 
// 왜냐하면 값을 새로 지정해줬기 때문이다. 





var myArray = [2, 3, 4, 5];
var ourArray = myArray;
ourArray[2] = 25;
ourArray = undefined;

myArray // [2, 3, 25, 5]

// 이경우에는 값이 변했다. 
// 왜냐하면 ourArray 가 myArray 메모리를 같이 쓰고있다가
// ourArray[2] = 25 로 바꾸웠기 때문에 myArray에 영향을 끼친다. 

// 하지만 
var myArray = [2, 3, 4, 5];
var ourArray = myArray;
ourArray = []

myArray // [2, 3, 4, 5];

// ourArray = [] 하면 myArray 에 영향을 주지 않는다. 
// ourArray = [] 빈배열로 정의하면 새로 배열을 만들었기 때문에
// myArray 에서 독립되서 메모리를 사용하기 때문이다. 


Callbacks, Promises, Async Await



// DATA

const posts = [
	{ title: "'Post One", body: 'this is post one'},
	{ title: "Porst One", body: "this is post two"}
];



// getPosts() 함수는 화면에 data 안에 있는 tile 을 출력해준다. 
// 1초후 출력한다. 

function getPosts() {
	setTimeout(()=>{
	let output = "";
	posts.forEach((post,index)=>{
		output = output + `<li>${post.title}</li>`
	});
	document.body.innerHTML = output;
	},1000);
}
getPosts();


// creatPost(post) 함수는 2초후에 data에 새로운 값을 추가해넣는다. 
// 2초후에 추가된다 추가될 내용은 createPost({title:"추가될 내용"}) 이거다.

function createPost(post){
	setTimeout(()=>{
		posts.push(post)
	},2000)
}


// 추가된 내용이 출력되지 않는다. 왜냐하면 getPosts() 가 출력된후에 
// creatPost 가 추가되었기 때문이다. 

createPost(title: "Porst Three", body: "this is post three"})

  • callback을 사용해서 추가한 값을 출력하기


function getPosts() {
	setTimeout(()=>{
	let output = "";
	posts.forEach((post,index)=>{
		output = output + `<li>${post.title}</li>`
	});
	document.body.innerHTML = output;
	},1000);
}
getPosts(); // 1.이 호출을 creatPost() 함수 인자값으로 넣는다. 

// 2.creatPost 안에 파라미터로 callback 을 만든다.
// 이것이 callback 을 쓰는 이유이다. 
function createPost(post,callback){
	setTimeout(()=>{
		posts.push(post)
		callback() // 3.콜백 함수를 여기서 실행한다.
	},2000)
}


createPost({title:"Post Three", body:'This is post three'},getPosts) //4.넣는다.



  • Promises 사용하해서 값을 추가하기


function getPosts() {
	setTimeout(()=>{
	let output = "";
	posts.forEach((post,index)=>{
		output = output + `<li>${post.title}</li>`
	});
	document.body.innerHTML = output;
	},1000);
}



function createPost(post) {
		// Prsomise 안에 코드작성 
	return new Promise((resolve,reject)=>{

		setTimeout(()=>{
			posts.push(post)
		
		// error 가 잇는지 없는지 검사하기 위한방식

			const error = false; 

			if (!error) {
				resolve(); // 에러가 겂다면 출력
			} else {
				reject("Error : something went wrong")
			}
		},2000);

	})

}
// .then(getPorsts)  여기에 함수를 넣는다.  
createPost({title:"Post Three",body:'This is post three'}).then(getPosts);



// 만약 에러메시지가 console 에 나오게 하려면

const error = true

		if (!error) {
				resolve(); 
			} else {
				reject("Error : something went wrong") // 이것이 나와야 한다. 
			}
		},2000);

	})

}

// .catch 라는 것을 사용한다. 
createPost({title:"Post Three",body:'This is post three'})
.then(getPosts).catch(e => console.log(e)); // console 창에 출력해라 


![](/tutorial/2019-11-26-js-post_files/Screen Shot 2019-12-18 at 5.42.03 PM.png)

  • Promise.all


const promise1 = Promise.resolve("Hello world");
const promise2 = 10;
const Promise3 = new Promise((resolve,reject)=>{
	setTimeout(resolve,2000, "GoodBye");
})

Promise.all([promise1,promise2,Promise3])
.then((val => console.log(val)))

# 객체지향프로그래밍(OOP)

  • 갹체 지향 프로그래밍이란(OOP: Object Oriented Programming)?

    • 객체 지향 프로그래밍(이하 OOP)는 컴퓨터 프로그램을 “객체(Object)“들의 모임으로 파악하고자 하는 프로그래밍의 패러다임 중에 하나이다. 각 “객체(Object)” 들은 서로 메시지를 주고 받을 수 있으며 데이터를 처리할 수 있다.
  • 객체 지향 프로그래밍 장점

    • 코드의 재사용성 제공 : 객체의 특성이나 속성을 한 번 정의해 놓으면 해당 객체에 소속되어 있는 모든 객체들의 속성으로 사용할 수 있으므로 재사용성이 높아진다.

    • 유지보수의 용이 : 한 번만 정의한 것을 수정하면 모든 객체의 속성을 수정할 수 있다.

    • 신뢰성 증대 : 다양하게 사용된 속성들에 경험이 쌓이면서 신뢰가 축적되기 쉽고 그것을 다시 사용한다면 에러(버그)의 가능성이 줄어든다.

  • OOP의 기본 구성 요소

    • 클래스(Class)

같은 종류의 집단에 속하는 속성과 행위를 정의한 것. 다른 클래스와 독립적으로 디자인해야 한다. 위의 예제에서 몬스터(Monster) 의 특성과 행위들을 정의한 객체가 클래스가 될 것이다.

  • 객체(Object)

클래스의 인스턴스(Instance). 상위 클래스의 속성을 가지고 있으면서 개별적인 특성과 행위(메소드 : Method) 또한 가지고 있다. 위의 예제에서는 드래곤, 좀비, 해골 등이 각각의 객체가 된다.

  • 메서드(Method)

클래스로부터 생성된 객체를 사용하는 방법. 객체의 속성을 조작하는 데 사용된다. 위의 예제에서 각각의 몬스터들이 레벨업을 하는 행위가 메서드(method)라고 볼 수 있다.

  • OPP 특성

캡슐화(Encapsulation), 추상화(Abstraction) ,재사용성

  • 예제)
  • 객체를 만든다.
  • 이 객체는 일반적으로 쓰는 Object Literal(객체 리터럴) 으로 생성됨
  • 외부에서 쉽게 프로포티 에 쉽게 접근할수 있다.
  • 예를 들어 level 을 바꾸는 경우가 있을수 있다.

var monster1 = {
  level : 0,
  habitat : 'forest',
  levelUp: function () {
    this.level++;
  }
};


  • 캡슐화(Encapsulation)

    • 캡슐화는 객체의 데이터를 외부에서 직접 접근하지 못하게 막고, 함수를 통해서만 조작이 가능하게 하는 작업이다.

    • 외부에서 var level = 0 접근 할수 없게 되었다.

    • 이전의 몬스터 객체처럼 monster.level로 몬스터의 level데이터에 접근할 수 없게 되었다. level은 오직 monster.levelUp이라는 메소드(method)로만 조작할 수 있다.


var monster = createMonster();
function createMonster () {
  var level = 0;
  var openInfo = {
    habitat : 'forest',
    levelUp : function () {
      level++;
    }
  };
  return openInfo;
}

  • 추상화(Abstraction)

    • 추상화는 객체들이 가진 공통의 특성들을 파악하고 불필요한 특성들을 제거하는 과정을 말한다

    • 예)


//몬스터들이 공격을 받아 healthPoint가 0이 되면 필드에서
//죽은 것(death)으로 처리하고 싶다.
//이용자들은 몬스터들을 공격하고 죽는 모습을 보기만 하면 된다.
//어떠한 과정을 거쳐서 몬스터가 죽었는지에 대해서는 알 필요가 없다.

  • 위의 케이스에서는 객체에 2가지 속성이 추가되어야 한다. 몬스터가 죽은 상태인지 살아있는 상태인지를 확인하는 속성, 그리고 healtpoint라는 속성이다. 위의 속성을 추가하고 공격을 받는 상황을 메소드(method)로 만들어보겠다.

var monster = {
  level : 0,
  habitat : 'forest',
  healthPoint : 100,
  isLive : true,
  levelUp: function () {
    this.level++;
  },

  damaged: function (damage) {
    this.healthPoint -= damage;
    if (this.healthPoint === 0){ 
       this.isLive = false;
    } 
  }
}

monster
// {level: 0, habitat: "forest", healthPoint: 100, isLive: true, levelUp: ƒ, …}
monster.damaged(20);

monster
// {level: 0, habitat: "forest", healthPoint: 80, isLive: true, levelUp: ƒ, …}
monster.damaged(20);

monster
//{level: 0, habitat: "forest", healthPoint: 60, isLive: true, levelUp: ƒ, …}
monster.damaged(20);

monster
//{level: 0, habitat: "forest", healthPoint: 40, isLive: true, levelUp: ƒ, …}
monster.damaged(20);

monster
//{level: 0, habitat: "forest", healthPoint: 20, isLive: true, levelUp: ƒ, …}

monster.damaged(20);

monster // healthPoint :0 되었고 isLive 는 false 가 되었다. 
//{level: 0, habitat: "forest", healthPoint: 0, isLive: false, levelUp: ƒ, …}


  • 재사용성

    • 몬스터를 여러마리 만든다고 가정하자

    • OOP의 가장 큰 특성 중 하나가 바로 코드의 재사용성상속의 개념이다. 같은 객체를 여러 개 만들어야 하는 경우, 한 번 작성된 코드를 활용하여 동일한 객체를 만들 수 있다.

function Monster () {
  this.healthPoint = 100;
  this.habitat = 'forest';
  this.level = 1;
}
Monster.prototype.levelUp = function () {
  this.level++;
}
var broMonster= new Monster();  // 몬스터1
var childMonster = new Monster(); // 몬스터 2
var parentMonster= new Monster(); // 몬스터 3


  • 위의 코드처럼 생성자 함수를 이용하는 방법 이외에도 Factory Function을 이용하는 방법도 있다. Factory Function은 간단히 객체를 리턴하는 함수라고 생각하면 된다.

var monsterPrototype = {
  levelUp : function () {
    this.level++;
  }
}
function createMonster () {
  var monster = Object.create(monsterPrototype);
  monster.level = 1;
  monster.habitat = 'forest';
  return monster;
}
var broMonster= new createMonster();
var childMonster = new createMonster();
var parentMonster= new createMonster();


# prototype 무엇이냐?

# 자바스크립트는 프로토타입 기반 객체지향 프로그래밍 언어이다.

  • ES6 문법이 도입되기 전에는 JavaScript에는 클래스(Class)가 없었음 그래서 객체 생성을 위해서 prototype을 사용했다.

  • 객체를 생성하면, 프로토타입이 결정되고, 우리는 그 프로토타입을 변경할 수 있습니다

  • 첫번째 알아야 할것

  • 함수를 만들어 변수에 담을때 new 라는 것을 같이 담으면 객체가 된다.

function Person() {}

let x = new Person(); //  x 라는 변수는 객체가 된다. 


  • 두번째 알아야할 것

  • 객체(object)는 함수(function)로부터 시작된다


function Book() { }                // 함수 <<생성자 함수
var jsBook = new Book();           // 객체 생성


  • 두가지 방식을 객체를 생성할수 있다.
var jsBook = new Book(); // 첫번째 방식 (생성자 함수) // 객체 

var jsBook = {}          // 두번째 방식(생성자 선언 없이 ) // 객체 


  • 세번째 알아야 할것

  • 함수 생성시 발생하는 것을 알아야 한다.

    • 1.함수를 정의하면 함수가 생성되며 Prototype object가 같이 생성 됩니다.

생성된 Prototype object는 함수의 prototype 속성을 통해 접근할 수 있습니다. (Prototype object같은 경우 함수 생성시(var jsBook = new Book())에만 됩니다. 일반 객체 생성시에는 생성되지 않습니다.)

  • 2.함수의 생성과 함께 생성된 Prototype object는 constructor와 __proto__를 갖고 있습니다.

constructor는 생성된 함수를 가리키며(여기서는 function Book을 가리킵니다.)

__proto__는 Prototype Link로서 객체가 생성될 때 사용된 생성자(함수)의 Prototype object를 가리킵니다.

  • 네번째 알아야 하는것

  • 객체(object) 생성시 발생하는 일

생성하는 순간 jsBook 이라는 객체는 proto 라는 _proto__라는 프로퍼티를 갖고있습니다.


function Book() { }

Book.prototype.name = "john" 

var jsBook = new Book() // jsBook 은 객체이다. 


prototype property(함수 생성시 함께 생성된 Prototype object를 가리킴)는 함수객체만 가지며 __proto__는 객체라면 모두 갖고 있습니다.

![](/tutorial/2019-11-26-js-post_files/Screen Shot 2019-12-16 at 2.39.56 PM.png)

prototype property(함수 생성시 함께 생성된 Prototype object를 가리킴)는 함수객체만 가지며 __proto__는 객체라면 모두 갖고 있습니다.

  • 예제)

  • 1.일반적인 함수 패턴




function Name(_name){
    var oName = {
        name : _name,
        getName : function(){
            return this.name;
        }
    }

    return oName;
}

Name('john'); // Object{name: 'siwa', getName:function()} 리턴
var x = Name('john');
x.getName(); // 'john' 리턴


  • 1.객체 생성자 함수의 활용 - 모듈화,프로토타입

    • new Key word 를 사용한다.

    • 이는 객체지향적인 언어를 표방하는 기능, 클래스를 만드는 것과 비슷하다.

    • (new라는 키워드는 자바에서 클래스를 호출해서 인스턴스를 만드는 것과 비슷하다)


 function Name(_name){
		console.log('this is',this);
		this.name = _name;
		this. getName = function(){
        return this.name;
    }
}

// 함수 를 그냥 호출했을때 와 new 키워드와 같이 호출했을때의 차이점 을 할수 있다. 

// 1. 함수를 그냥 호출했을때
Name('john'); // this is window, undefined 리턴

// 2. new 키워드와 함께 함수를 호출했을 때
new Name('john'); // this is Name{}, Name{name:'monkey', getName()} 리턴



var x = new Name('john');

x.getName(); // 'john'




  • 2.객체 생성자 함수의 활용 - 모듈화프로토타입

    *기능별로 모듈화 시킨 독립적인 클래스 단위로 그루핑할때 생성자 함수를 활용할 수 있다.

    • 예를 들어 구글지도 UI를 만들 때, 화면에 보이는 기능 단위 즉 의미적으로 다른 기능이라면 (ex. 사진, 공유, 검색, 지도화면, 설정) 각각의 기능을 별도 모듈(클래스 단위)로 만들 수 있다.

// 모듈화 수도코드 예시
// 지도를 표현하는 영역 클래스

function Map(name){
    this.name = "john"
    }
    
// 지도를 검색하는 영역 클래스
function SearchMenu(){}

// 사진을 슬라이드 하는 영역 클래스
function ViewCurrentPhotos(){}


var oMap = new Map("john");

 // 여기서 setDraw 를 설정해준다.
Map.prototype.setDraw = function (){
    console.log(name + "그림을 그리네 ?");
}

oMap.setDraw() // john 그림을 그리네?


  • 3.객체 생성자 함수의 활용 - 모듈화프로토타입



function Car(band,name,color) {
    // 인스턴스가 만들어 질때  실행될 코드들... 
}

// new 키워드를 통해 클라스의 인스턴스를 만들어낼 수 있습니다. 



// 1. 속성  : band,name,color , currentFuel,maxSpeed
// 2. 메소드  : refuel() ,setSpeed(), drive()



// ex


// 1. 클라스 함수 와 인스턴스 생성 

function Car(brand,name,color) { // Car() 는 클라스
	
	this.what_brand = brand; // 여기서 this 는 인자값이 드러갈 변수이름 (avante)
	this.what_name = name;	
	this.what_color = color;
}

// 2. 클라스 함수를 변수에 담고 파라미터 들어갈 값들 넣는다. 

let avante = new Car("GM","avante","black"); // 변수를 만든다 (인스턴스값으로 들어갈 )

// 3. 추가로 인스턴스를 생성 

Car.prototype.what_drive = function () { // Car() 인스턴스 생성 그리고 function 는 인스턴스 값  
    console.log(this.name + "가 운전을 합니다. ");
}


avante.what_name // 인스턴스 값 출력
// "avante"
avante.what_brand
// "GM"
avante.what_color
// "black"

avante.what_drive()  // 새로 생성한 what_drive 출력 
// jj 가 운전을 합니다. 

`tip`

let arr = [1,2,3,4,5]     // 배열 만들기 
let arr = new Array(1,2,3,4,5) // 배열 만들기  // Array클라스 안에 (인자값들) 




// ES6  에서는 클라스라는 키워드를 이용해서 정의 할수 있다. 


class car {
	constructor(brand,name,color) {
	
	// 인스턴스가 만들어질 때 실행되는 코드
		}
}



# 생성자 함수 || prototype 객체 || instance

![](/tutorial/2019-11-26-js-post_files/Screen Shot 2019-12-04 at 9.14.37 AM.png)

  • 생성자 함수 만들기
// 생성자 함수 를 만든다. 

function Class(name, age,yesNo) {
  this.name = name
  this.age = age
  this.yesNo = yesNo
  
}

// 동작을 만들기 위해 stydy 함수를 생정자 함수안에 추가한다.  
// 이때 prototype 을 만든다. 

Class.prototype.study = function(){
  console.log(this.name + " 운전을 합니다. ")
}


// 인스턴스 만든다. 
let obj = new Class("join",33,"좋아 이녀석아");

obj.study(); // join 운전을 합니다.


# 함수 메소드 call(),apply,bind()

함수를 불러올때 유요한 메소드들

불로오는 방식이 들림

  • add.call(obj,2,3);

  • add.apply(obj,[2,3]); (배열로 인자값을 넣는다.)

  • let boundFn = add.bind(obj,2,3)

boundFn <== this 값이 묶여 있다.

call은 실행되는 함수의 this값을 원하는 객체로 바꿔서 실행할 수 있게 해준다.

bind는 실행되는 함수의 this값을 원하는 객체로 고정시키는 새로운 함수를 만들어낸다.

  • call() , apply()

// this 값을 넘겨주는 방식이 틀림
// call() and apply()  사용해서 함수안에있는 parameter 사용하기 

//  add.call(obj,2,3);   obj << this 2,3 <<<x y
//  add.apply(obj,[2,3]);   obj << this 2,3 <<<x y

// 만약 this 가 add 함수 안에 없으면 
// add.call(null,2,3); 

var obj = { 
val : 0
}; 

//  리턴값이 출력되는 것이 아니라 this값이 obj 가 됨으로 obj.val =  2 +3 // 이것을 해주기 위해  add.call(obj,2,3); or add.apply(obj,[2,3]);
var add = function  ( x , y ) {
	this.val = x + y ;   


add.call(obj,2,3);  // 5 동일다. 

add.apply(obj,[2,3]); // 5  동일하다. 


  • call(), apply 어떻게 쓰냐?

  • call, apply로 prototype 기능 빌려쓰기


let arr = ["code","states"]; 

//5보다 많은 length 가져오고 싶을때 filter 를 쓰게 된다. 
//그런데 call() 과 applay 를 이용해서 가져올수 있다. 

Array.prototype // 이럴때 필요 이라는 것이 필요하다. 

function moreThanFive(str) {
	return str.length > 5;
}


//첫번째 방법

arr.fillter(moreTahnFive) 

//두번째 방법

Array.prototype.filter.call(arr,moreThanFive)
Array.prototype.filter.apply(arr,[moreThanFive])


  • 배열이(유사배열) 같아 보이지만 배열이 아닌경우

let list = document.querySelectorAll("a")

//a 라는 selector를 모두가져와서 ID를 출력하고 싶다. 
//그럼 배열안에 Id 를 가져올때 map 을 쓸것이다. 
//그런데 실제로 이것은 배열 이아니기 때문에 map 메소드를 쓸수 없다 .

//이것을 배열로 인식하고 map 메소드 등을 이용해서 가공하기 위해서는 
//사용하기 위해서는  call(), apply()를 사용해서 가져와야 한다. 

function getElementId(element) {
	return element.id
}
list.map(getElementId) // 오류가발생한다. 왜냐하면 list 는 array 가 아니가 때문이다. 

// 이것을 되게 하는 방법

Array.prototype.map.call(this,getElementId) // this 값인 list 를 넣어주고 함수를 두번째 에 넣어주면  값이 실행된다. 



  • applly() 어디다 쓰느냐?
	
// arr 안에 가장 큰수를 가져오는 방법 apply() 메소드 써서 가져올수 있다.

let arr = [1,2,3,4,5,6];


Math.max.apply(null,arr); //apply 는 배열을 담으니까 큰수를 가져온다.  

// 6

  • bind() 언제 유용하냐 ?

  • 1.특정 함수가 this 값을 바꿔버리는 경우

  • setTimeout()


// 생성자 함수가 있다. 

function Class(name, age,yesNo) {
  this.name = name
  this.age = age
  this.yesNo = yesNo
  this.workingHard = function(){
	return this.yesNo;
	}
  this.study = function() {
	console.log(this.workingHard());
	}
  
}

// 인스턴스 obj 을 지정한다. 

let obj = new Class("join",33,"좋아 이녀석아");

// study() 를 실행해서 workingHard() 실행하면  this.yesNo 가 실행 "좋아 이녀석아" 실행된다. 

// 하지만 setTimeout안에서는 this 값이 바꿔지기 때문에 실행이 안된다. 

setTimeout(obj.study,2000)


// 그래서 bind() 사용해서 실행한다. 
setTimeout(obj.study.bind(obj),2000)

//"좋아 이녀석아"; 

  • 2.bind로 커링 구현하기

  • 인자값을 고정시키고 쓸때


function template(name,money) {
	// name 값을 지정하고 쓸것이다.
   return "<h1>"+name+"</h1>" + "<span>"+money+"</span>"
}


let temJohn = template.bind(null,"john") // join 지정하고 바인드 해둔 것을 변수에 담는다 (커링)

temJohn(200); // "<h1>john</h1><span>200</span>"

let temEsther = template.bind(null,"esther");
temEsther(2000); // "<h1>esther</h1><span>2000</span>"

# This

  • Execution context (실행컨텍스트)

  • 어떤 함수가 호출되면, 실행 컨텍스트 execution context가 만들어진다

    • call stack에 push

    • 함수를 벗어나면 call stack에서 pop

  • scope별로 생성

  • 여기에 담긴 것

    • scope내 변수 및 함수 (Local, Global)

    • 전달인자 (arguments)

    • 호출된 근원 (caller)

    • this

![](/tutorial/2019-11-26-js-post_files/Screen Shot 2019-12-03 at 3.37.25 PM.png)

  • this keyword
  • 모든 함수 scope 내에서 자동으로 설정되는 특수한 식별자

  • execution context의 구성요소 중 하나로, 함수가 실행되는 동안 이용할 수 있다

  • this === execution context 라고도 말한다.

  • this 는 5가지 patterns 이 있다.

// 1. global this // 2. function invocation // 3. method invocation // 4. construction mode // 5. call(), .apply()

\

Contruction ==< 생성자 함수

  1. Method Invocation : call, apply의 첫번째 인자로 명시 된 객체, .을 기준으로 왼쪽에있는 객체
  • 생성자함수 만들기 (객체)

  • 생성자는 new로 객체를 만든다.

function Class(name, age) {
  this.name = name
  this.age = age
  
}

const obj1 = new Class('john', '33') // Class의 인스턴스 생성 
console.log(obj1.name) // jogn
console.log(obj1.age) // 33

const obj2 = new Class('esther', '30')
console.log(obj2.name) // essther
console.log(obj2.age) // 30


  • 일반 객체 만들기 (객체 )

const person1 = {
  name: 'john',
  age: 33,
  yourName: function() {
    return this.name
  }
}
console.log(person1.yourName()) // john

const person2 = person1 // person1 을 person2 에 넣는다.  
person2.name = 'esther' // 그리고 값을 바꾼다.


console.log(person1.yourName()) // person1 출력 :esther 

console.log(person2.yourName()) // person2 출력 :esther 

// person2 를 바꿨는데 person1 에 있는 name 까지 바뀌었다. 
// 왜냐하면 person2는  person1 레퍼런스 변수이므로 하나 이기 땨문이다. 



  • how to use this with call()



function bar () {
  console.log(this);
}

bar.call({a:1}); // {a:1}


function bar () {
  console.log(this.a);

}

bar.call({a:1}) // 1





# Closure 1

  • 클로저란?

함수는 함수를 리턴할수 있다.그것을 고차함수라고 하는데 그것을 클로저라 부른다. 한마디로 외부함수의 변수에 접근할수 있는 함수클로저라 부른다.

  • 특징 ?

클로저 함수의 장점은 지역변수 외부 함수의 변수 전역 변수 에 접근이 가능하다는 점이다 !




function foo() {
  return function() {
        return 2 
    }
}

foo() // f

// 2 가 반환되지 않고 
//f << 함수 자체가 리턴된다 

  • 클로저예제1 : 함수 이용해서 템플릿 함수 만들기



function htmlMark(tag) {
    let stratTag = "<" + tag + ">" ; 
    let endTag = "<" + tag + ">" ;
      return function(content) {     //  클로저 함수 사용 
        return stratTag + content + endTag;
    }
}

htmlMark("h1")("JJ"); // 커링 사용해서 출력 tag : "h1" content:"JJ"
// >>> <h1>JJ<h1>

let h1Tag = htmlMark("h1"); // 변수에 tag:"h1"담아서 지정하고 출력 

h1Tag("JJ")  //  content : "JJ"
// >>> <h1>JJ<h1>

  • 클로저예제 2 : 클로저 모튤 패턴



// 두 카운터가 각기 다른 privateCount 를 다루면서, privareCounter 을 밖에 노출시키지 않는 것이 장점이다. 

function makeCounter() {
	let privateCounter = 0; 

	let obj = {
	  plus : function() {
		  privateCounter = privateCounter + 1;
	  },	
	  minus: function() {
		  privateCounter = privateCounter - 1;
	  },
	  getValue: function() {
		  return privateCounter;
	  }
  }
  return obj;
};

let count1 = makeCounter() // 함수를 변수에 지정한다. 
count1.plus() // obj key값을 실행시키면 propo 값인 함수가 실행되면서 기존에 privateCounter 0 이였던 것을 1 증가시킨다. 

coun1.getValue() //  obj key값인 getValue() 함수를 실행시키면 지금까지 plus 하고 minus한 값을 출력 할수 있게 코드가 짜여 있다. 


# Closure 2

  • 클로져란?

클로저는 독립적인 (자유) 변수를 가리키는 함수이다. 또는, 클로저 안에 정의된 함수는 만들어진 환경을 ‘기억한다’.

내부함수는 외부함수의 지역변수에 접근 할 수 있는데 외부함수의 실행이 끝나서 외부함수가 소멸된 이후에도 내부함수가 외부함수의 변수에 접근 할 수 있다. 이러한 메커니즘을 클로저라고 한다.





// 일반적인 함수


let addTo = function (passed) {

	let inner = 2;
	return passed + inner; 3 + 2 

};

console.log( addTo(3) ) //  5


//이것이 클로저

let passed = 3;  // 함수 밖에 변수를 선언한다 

let addTo = function () { //  parameter 를 외부에서가져온다. 

	let inner = 2;
	return passed + inner; 3 + 2  // 

};

console.log( addTo() ) //  5

# Closure 3

클로저(closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킨다.

자바스크립트에서 함수는 일급객체이다. 함수를 호출했을때 리턴되는 함수(클로저)를 참조하고 있는 것이다.

즉 반환되는 내부함수가 클로저이다.


function outter() {
    
    var title = '난 영혼처럼 살아있다.';
    
    return function() {
        
        console.log(title); // 클로저로 참조되는 외부변수를 자유변수(Free Variable) 라 부른다.
        
    };
};
 
var inner = outter();  // 생명 주기가 끝난 외부함수의 변수를 참조하는 내부함수를 클로저라 한다.  
inner();  // 결과 : 난 영혼처럼 살아있다. 
 
 
 

// 매번 호출할때 마다 변수값을 유지하고 싶을때 사용한다.
// 클로저가 참조하고 있는 변수를 노출시키지 않는다 (캡슐화)
// 클로저에서는 접근할수 있지만 코드 외부에서는 접근할수 없다.

var a = function() {
    
    var count = 0;
 
    return function() {
         return count++;
    };
};
 
let next = a();
 
console.log(next());  
console.log(next());  
console.log(next());  
console.log(next());  



# Closure 4

  • 추가설명 & 코드를 작성할때 많이 격는 어려움

클로저는 JavaScript의 유효범위 체인을 이용하여 이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 방법입니다. 외부 함수가 종료되더라도 내부함수가 실행되는 상태면 내부함수에서 참조하는 외부함수는 닫히지 못하고 내부함수에 의해서 닫히게 되어 클로저라 불리 웁니다. 따라서 클로저란 외부에서 내부 변수에 접근할 수 있도록 하는 함수입니다.

내부 변수는 하나의 클로저에만 종속될 필요는 없으며 외부 함수가 실행 될 때마다 새로운 유효범위 체인과 새로운 내부 변수를 생성합니다. 또, 클로저가 참조하는 내부 변수는 실제 내부 변수의 복사본이 아닌 그 내부 변수를 직접 참조합니다




function outerFunc(){  
    var a= 0;
    return {
        innerFunc1 : function(){
            a+=1; // a =  a + 1;
            console.log("a :"+a);
        },
        innerFunc2 : function(){
            a+=2; // a = a + 2;
            console.log("a :"+a);
        }
    };
}
var out = outerFunc();  
out.innerFunc1();  
out.innerFunc2();  
out.innerFunc2();  
out.innerFunc1();

//실행결과
/*
a = 1  
a = 3  
a = 5  
a = 6  
*/
function outerFunc(){  
    var a= 0;
    return {
        innerFunc1 : function(){
            a+=1;
            console.log("a :"+a);
        },
        innerFunc2 : function(){
            a+=2;
            console.log("a :"+a);
        }
    };
}
var out = outerFunc();  
var out2 = outerFunc();  
out.innerFunc1();  
out.innerFunc2();  
out2.innerFunc1();  
out2.innerFunc2();


//실행결과

/*
a = 1  
a = 3  
a = 1  
a = 3  
*/

  • [예제 8] 클로저의 상호작용, 서로 다른 객체

위의 코드는 클로저의 예제 코드이며 그 중 좌측 코드는 서로 다른 클로저가 같은 내부 변수를 참조하고 있다는 것을 보여주고 있습니다. 서로 다른 클로저 innerFunc1과 innerFunc2가 내부 변수 a를 참조하고 a의 값을 바꿔주고 있습니다. 실행 결과를 보면 내부 변수 a의 메모리를 같이 공유한다는 것을 알 수 있습니다.

우측 코드는 같은 함수를 쓰지만 서로 다른 객체로 내부 변수를 참조하는 모습입니다. 외부 함수가 여러 번 실행되면서 서로 다른 객체가 생성되고 객체가 생성될 때 마다 서로 다른 내부 변수가 생성되어 보기엔 같은 내부 변수 a로 보이지만 서로 다른 내부 변수를 참조합니다.

  • 클로저의 사용이유

클로저를 사용하게 되면 전역변수의 오,남용이 없는 깔끔한 스크립트를 작성 할 수 있습니다. 같은 변수를 사용하고자 할 때 전역 변수가 아닌 클로저를 통해 같은 내부 변수를 참조하게 되면 전역변수의 오남용을 줄일 수 있습니다. 또한, 클로저는 JavaScript에 적합한 방식의 스크립트를 구성하고 다양한 JavaScript의 디자인 패턴을 적용할 수 있습니다. 그의 대표적인 예로 모듈 패턴을 말 할 수 있는데 모듈 패턴의 자세한 내용은 [Javascript : 함수(function) 다시 보기]을 참고 하시면 될 것 같습니다. 마지막으로 함수 내부의 함수를 이용해 함수 내부변수 또는 함수에 접근 함으로써 JavaScript에 없는 class의 역할을 대신해 비공개 속성/함수, 공개 속성/함수에 접근을 함으로 class를 구현하는 근거 입니다.

  • 3.2 클로저 사용시 주의할 점

클로저를 사용할 때 주의해야 할 점이 여럿 있습니다. 제가 알려드리고 싶은 주의 점은 다음과 같습니다.

for 문 클로저는 상위 함수의 변수를 참조할 때 자신의 생성될 때가 아닌 내부 변수의 최종 값을 참조합니다.

<body>  
    <script>
    window.onload = function(){
        var list = document.getElementsByTagName("button");

        for(var i =0, length = list.length; i<length; i++){
            list[i].onclick=function(){
            console.log(this.innerHTML+"은"+(i+1)+"번째 버튼입니다");
            }
        }
    }
    </script>
<button>1번째 버튼</button>  
<button>2번째 버튼</button>  
<button>3번째 버튼</button>  
</body>  


//실행결과

/*
1번째 버튼은 4번째 버튼입니다  
2번째 버튼은 4번째 버튼입니다  
3번째 버튼은 4번째 버튼입니다  
*/

  • [예제 9] for문안의 클로저

위의 코드는 각각의 버튼에 이벤트를 걸어 클릭된 버튼이 몇 번째 버튼인지를 알기 위한 예제 입니다. 하지만, 실행 결과 값은 바라던 결과가 나오지 않습니다. 위의 클로저인 클릭 이벤트가 참조 하는 변수 i의 값이 버튼이 클릭될 때의 값이 아닌 for 구문을 다 돌고 난후 i의 값 4를 참조하기 때문에 모두 4라는 결과가 나옵니다.

<body>  
    <script>
    window.onload = function(){
        var list = document.getElementsByTagName("button");

        var gate = function(i){
            list[i].onclick=function(){
            console.log(this.innerHTML+"은"+(i+1)+"번째 버튼입니다");
            }
        }
        for(var i =0, length = list.length; i<length; i++){
             gate(i);
        }
    }
    </script>
<button>1번째 버튼</button>  
<button>2번째 버튼</button>  
<button>3번째 버튼</button>  
</body>


//실행결과
/*
1번째 버튼은 1번째 버튼입니다  
2번째 버튼은 2번째 버튼입니다  
3번째 버튼은 3번째 버튼입니다  
*/


  • [예제 10] 예제9 해결법 : 중첩클로저

위의 예제 코드를 통해 중첩 된 클로저를 사용하는 것 만으로 위와 같은 문제를 피하여 원하는 값이 나옵니다.

성능문제 클로저가 필요하지 않는 부분에서 클로저를 사용하는 것은 처리 속도와 메모리 면에서 좋은 방법이 아닙니다.


function MyObject(inputname) {  
    this.name = inputname;
    this.getName = function() {
        return this.name;
    };
    this.setName = function(rename) {
        this.name = rename;
    };
}
var obj= new MyObject("서");  
console.log(obj.getName());  


//실행결과
/*
*/

  • [예제 11] 클로저의 오남용

위의 코드와 같은 함수 내부의 클로저 구현은 함수의 객체가 생성될 때마다 클로저가 생성되는 결과를 가져옵니다. 같은 구동을하는 클로저가 객체마다 생성이 된다면 쓸데없이 메모리를 쓸데없이 차지하게 되는데, 이를 클로저의 오남용이라고 합니다. 클로저의 오남용은 성능 문제 면에서 안 좋은 결과를 가져옵니다.


function MyObject(inputname) {  
    this.name = inputname;
}
MyObject.prototype.getName = function() {  
    return this.name;
};
MyObject.prototype.setName =   function(rename) {  
    this.name = rename;
};
var obj= new MyObject("서");  
console.log(obj.getName());  

//실행결과
/*
*/

  • [예제 12] prototype객체를 이용한 클로저 생성

클로저를 위의 코드와 같이 prototype객체에 생성하게 되면 객체가 아무리 생성되어도 클로저를 한 번만 생성하고 여러 객체에서 쓸 수 있게 되어 메모리의 낭비를 줄입니다.

this와 arguments객체 클로저를 통해서는 외부함수의 this객체와 arguments객체를 참조하지 못합니다.


function f1(){  
    function f2(){
        console.log(arguments[0]);
    }
    return f2;
}
var exam = f1(1);  
exam();

//실행결과
/*
undefined  
*/

function f1(){  
    var a= arguments[0];
    function f2(){
        console.log(a);
    }
    return f2;
}
var exam = f1(1);  
exam();  

//실행결과
/*
1  
*/

  • [예제 13] arguments객체 참조

위의 좌측코드같이 클로저를 통해 arguments객체를 참조하게 되면 undefined라는 실행결과가 나옵니다. 즉, arguments객체는 참조가 불가능하며 굳이 참조하고 싶다면 오른쪽 코드와 같이 새로운 내부 변수에 arguments객체의 값을 넣고 그 변수를 참조 하거나 매개변수를 만들어 매개 변수를 참조하여야 합니다.


Function 생성자

var a= 20;  
function function1(){  
    var a= 10;
    var function2 = new Function("","return a;");
    return function2;
}
var exam = function1();  
exam();  
//실행결과
/*
20  
*/

// [예제 14] Function생성자로 선언된 클로저

// 위의 코드와 같이 클로저가 Function생성자로 생성된 경우 전역에서 생성된 것으로 인지합니다. 클로저 function2를 통하여 내부 변수 a를 참조하려고 했지만 원했던 결과와 달리 전역 변수 a가 참조 됩니다.



function outerFunc(){  
    var outer_val = {};
    function innerFunc(){
        console.log(outer_val);
    }

    outer_val.values = innerFunc;
    return innerFunc;
}

  • [예제 15] 인위적 순환참조

위의 코드는 의도적으로 클로저의 순환참조를 만든 예제 코드입니다. 내부 객체 outerval의 속성 값 values 에 내부 함수 innerFunc를 참조하게 만들고 내부 함수 innerFunc는 내부 객체 outerval을 호출 하고 있습니다. 위와 같은 순환 참조는 서로를 참조 하면서 영원히 끝나지 않는 호출로 인하여 메모리 누수를 야기합니다.


function outerFunc(){  
    var outer_val = {};
    function innerFunc(){
        console.log("Hello");
    }
    outer_val.values = innerFunc;
    return innerFunc;
}

// [예제 16] 의도치 않은 순환참조

// 그렇다면 위 코드같이 서로를 참조를 하지 않게 되면 순환참조가 끊어질까요? 아닙니다. JavaScript의 클로저는 특별한 문법을 쓰지 않고도 암묵적으로 생기는 특성을 가지고 있습니다. 이는 클로저를 쉽게 만들도록 해주지만 클로저가 사용되는 곳을 사용자가 식별하기 어렵게 만들기도 합니다. 그렇게 되면 내부 함수의 innerFunc는 암묵적으로 상위 함수의 내부 객체인 outer_val을 참조하게 되고 이로인해 의도치 않게 순환참조가 만들어집니다. 이런 의도치 않은 순환참조는 메모리 누수를 야기합니다.

// 이 같은 의도치 않은 순환참조는 객체가 제거될 때 명시적으로 null값으로 초기화 해 주거나 try-catch-finally구문으로 해결합니다. 또는 더 글라스 크락포드가 제시한 purge함수를 쓰게 되면 순환참조를 해결할 수 있습니다. 아래는 purge함수 입니다.

function purge(d) {  
    var a = d.attributes, i, l, n;
    if (a) {
        for (i = a.length - 1; i >= 0; i -= 1) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            purge(d.childNodes[i]);
        }
    }
}


# 커링 (currying)

  • 커링이란?

호출된 함수의 매개변수로 동적으로 새로운 함수를 생성하여 반환하는 패턴을 커링이라 한다.

호출하는 함수의 인자값이 비슷하다면 커링을 사용하는 것이 효율적이다.

클로저를 이용해 함수의 인자를 미리 등록해두는 것


function func(a) {
    return function(b) { // 내부 함수, 즉 클로저인 익명 함수 반환
        return a + b;
    }
}
var currying = func(5);
var result = currying(5); 
console.log(result);

// 또는 아래처럼 호출
var result2 = func(5)(7); 
console.log(result2);

https://mylife365.tistory.com/320 

# Scope

  • 스코프란?

  • 자바스크립트에서 스코프란 어떤 변수들에 접근할 수 있는지를 정의합니다.

  • 스코프엔 두 가지 종류가 있습니다. 전역 스코프와 지역 스코프로 나뉩니다.

전역_스코프




let greeting = 'Hello John' // 외부에서 변수가 선언됨

function marcusHello () {
  console.log(greeting)
}

console.log(greeting) // 'Hello John!' 

sayHello() // 'Hello John!' 


지역_스코프




function marcusHello () {
  
  let greeting = 'Hello John!' // 안에서 변수가 선언됨
  console.log(greeting)
}

marcusHello() // 'Hello John!!'

console.log(x) // Error, hello is not defined


let name = "john";

function showName() { 
  let name = "jj"; // 2. 지역변수 << showName함수에서만 접근 가능
  console.log(name); // 2. jj
}

console.log(name); // 1.john << 전역변수 가져옴
showname()         // 2.jj 
console.log(name)  // 3. john << 여전히 전역 변수 john





let name = "john";

function showName() {
  name = "jj"; // name 이 전역변수로 바뀜 cos let 없기 때문에 외부에서 변수 가져왔다. 
  console.log(name); //   jj 
}

console.log(name); // 1. john << 전역변수 가져옴
showName()         // 2. 
console.log(name)  // 3. jj 함수가 실행된 뒤에는 함수안에 있는 name = jj 를 가져와서 리턴한다. 왜냐하면 jj 가 전역 변수로 바뀌었기 때문이다. 


# Number Methods

    1. Number.isInteger()
  • 숫자가 인지 아닌지 확인

  • return : boolean


Number.isInteger(1) // ture;
number.isInteget("1") // false;



    1. Number(), parseFloat(), parseInt()
  • 문자열을 숫자로 바꾸는 함수


Number("12,32"); // Nan 소수점이 있으면 반환 안된다. 

parseInt("123.2323"); // 123 소수점뒤에는 버린다. 
parseFloat( '12.34' ) // 12.34 소수점까지 포함해서 숫자로 반환해준다.

    1. toFixed();
  • 소수점이 길면 자르는 역활

  • 반환값 : string

let num = 123.2342323123231232312323123231232312323
num.toFixed(3) //  "123.234" // string 으로 반환


# Math Methods

    1. Math.max() / Math.min()
  • 가장 큰수 리턴


Math.max(2,3,2,4,52)

// 52

  • 가장 작은수 리턴
Math.min(2,3,2,4,52)

// 2


  • 2.floor()

  • 소수점을 가장 가까운 정수로 내림한 값을 리턴

  • return : numnber , 정수

alert(Math.floor(5.1)); // number, 5
alert(Math.floor(5.9)); // number, 5
alert(Math.floor(5)); // number, 5
alert(Math.floor(-5.1)); // number, -6
alert(Math.floor(-5.9)); // number, -6


  • 3.round()

  • 소수점을 가장 가까운 정수로 리턴한다.

  • return : number;



alert(Math.round(5));   // number, 5
alert(Math.round(5.6)); // number, 6 // 올라간다. 
alert(Math.round(5.4)); // number, 5

4.random()

  • 0과 1사이의 랜덤한 수를 리턴

*0과 1사이의 수를 리턴함

  • Math.random()의 리턴값에 수를 곱하면 0부터 곱한 수 사이의 랜덤한 값을 구할 수 있다

  • 랜덤한 수를 발급하거나, 시스템적으로 불규칙한 행위가 필요할 때 사용

alert(Math.random()*100); // number, 0~100 사이의 랜덤한 값을 리턴
alert(Math.ceil(Math.random()*100)); // number, 0~100 사이의 랜덤한 값을 올림한 정수를 반환



5. abs()

  • 인자로 전달된 값에 대한 절대값을 리턴함

6. sqrt()

  • 제곱근을 리턴함

  • 사용방법 : Math.sqrt([대상 숫자]);

ex


// 1024의 제곱근을 구하시오.

Math.sqrt(1024) : 32



alert(Math.sqrt(25)); // number, 5
alert(Math.sqrt(100)); // number, 10
alert(Math.sqrt(5)); // number, 2.23606797749979
alert(Math.sqrt(-5)); // Nan, 제곱근은 음수일 수 없음


7.pow

  • 거듭제곱을 리턴한다.

  • Syntax : Math.pow(a,n)

  • 사용방법 : Math.pow([대상 숫자], [거듭제곱 횟수]);

ex


// 숫자 2를 5번 거듭제곱하여 그 결과를 출력하시오.

Math.pow(2, 5)      // : 32
// 2* 2* 2 * 2 * 2  // : 32


//절대값이란 실수에서 부호를 제거한 값을 의미한다. 
// 3과 -3의 절대값은 3이 된다.
alert(Math.abs(-3)); // number, 3


Callback




// 장점 


/*
원래의 내장메소드에 있는 기능을 콜백 으로 바꿔서 사용할수 있다.

값으로 사용될 수 있는 특성을 이용하면 함수의 인자로 함수로 전달할 수 있다. 값으로 전달된 함수는 호출될 수 있기 때문에 이를 이용하면 함수의 동작을 완전히 바꿀 수 있다. 인자로 전달된 함수 sortNumber의 구현에 따라서 sort의 동작방법이 완전히 바뀌게 된다.

ajax를 사용할때 제이 쿼리를 이용해서 콜백이 사용된다. 


*/

function sortNumber(a,b){
    // 위의 예제와 비교해서 a와 b의 순서를 바꾸면 정렬순서가 반대가 된다.
    return b-a;
}
var numbers = [20, 10, 9,8,7,6,5,4,3,2,1];
alert(numbers.sort(sortNumber)); // array, [20,10,9,8,7,6,5,4,3,2,1]

![](/tutorial/Javascript_Notes_files/Screen Shot 2019-07-17 at 4.46.43 PM.png)


// 콜백 함수를 사용해서 함수 사용해기 

// first = element
// second = index
// third = array

function foo(first,second,third) {
	if ( first > second ) {
		console.log(first);
	} else {
		console.log(second);  
	}
}

function forEach(arr,test) {
	for (let i = 0; i < arr.length; i = i + 1 ) {
		foo(arr[i],i,arr); // 함수
    	}
	}

salesTeam 안에 있는 data fliter 와 foreach 로 다루기

var salesTeam = [
  {
    "name": {
      "first": "Bruce",
      "last": "Wayne"
    },
    "age": 10,
    "sales": "$2314"
  },
  {
    "name": {
      "first": "Alvaro",
      "last": "Angelos"
    },
    "age": 55,
    "sales": "$1668"
  },
  {
    "name": {
      "first": "Alvaro",
      "last": "Angelos"
    },
    "age": 15,
    "sales": "$1668"
  }
];


// age 가 20 아래인 것만 teenager 에 담기 
// filter 사용

let teenager = salesTeam.filter(function(ele){
    return ele.age < 20;
  });

// 뽑은거 안에서 fullNmae 가져오기
// foreach 사용

  let result = [];
  teenager.forEach(function(ele){
    result.push(`${ele.name.first} ${ele.name.last}`);
  });



# from()

  • Definiton & Syntax

Array.from(arrayLike[, mapFn[, thisArg]])

  • 리턴 새로운 Array 인스턴스

  • MDN

Array.from()은 선택 매개변수인 mapFn를 가지는데, 배열(혹은 배열 서브클래스)의 각 요소를 맵핑할 때 사용할 수 있습니다. 즉, Array.from(obj, mapFn, thisArg)는 중간에 다른 배열을 생성하지 않는다는 점을 제외하면 Array.from(obj).map(mapFn, thisArg)와 같습니다. 이 특징은 typed arrays와 같은 특정 배열 서브클래스에서 중간 배열 값이 적절한 유형에 맞게 생략되기 때문에 특히 중요합니다.

  • string 받아서 배열로 바꿈


console.log(Array.from('foo'));
// expected output: Array ["f", "o", "o"]

console.log(Array.from([1, 2, 3], x => x + x));
// expected output: Array [2, 4, 6]


  • set 사용해서 중복된 값 제거


const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set);
// [ "foo", "bar", "baz" ]


  • arguments 도 받아서 배열로 만들어 버린다.


function f() {
  return Array.from(arguments);
}

f(1, 2, 3);

// [ 1, 2, 3 ]
  • map 으로 사용하기 배열안에 배열

values 값 얻기


var a = new Map([['1', 'a'], ['2', 'b']]) // 각요소의 1번째 가 키 2번째가 값 

Array.from(a.values()); // 새로운 array 출력한다. 

["a", "b"] //값

keys 값 얻기


var a = new Map([['1', 'a'], ['2', 'b']]) // 각요소의 1번째 가 키 2번째가 값 

Array.from(a.values()); // 새로운 array 출력한다. 

["a", "b"] //값


  • 내가 원하는 수만큼 배열 만들기


Array.from({length: 5}, (val, index) => index);

// [0, 1, 2, 3, 4]


function add (val,index) {
return index;
}



Array.from({length: 5},add) // [0, 1, 2, 3, 4]


# reduce()

  • Definiton & Syntax

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

  • accumulator — the accumulator accumulates all of the callbacks returned values.

  • val — the current value being processed

  • index — the current index of the value being processed

  • arr — the original array

The reduce() method is used to apply a function to each element in the array to reduce the array to a single value.

여러게의 값이 담긴 배열이 줄여서(reduce) 최종적으로 하나의 값으로 만드는 과정

  • 리턴값이 반듯이 필요

  • 누적값 : 배열의 요소를 하나하나 줄여가면서 생기는 중간 과정(결과)

  • 현재값 : 리듀서가 배열을 지나갈 떄 만나는 배열의 요소

  • 초기값 : 배열의 요소를 줄이기 전 누적값의 초기 상태

  • ex)

  • Reduce vs. For Loop

  • 배열에서 숫자로

  • To use for Loop


let arr = [1, 2, 3, 4];
let sum = 0;
for(var i = 0; i < arr.length; i++) {
    sum += arr[i];
}
// sum = 10


  • To use the reduce() function
  • 배열에서 숫자로
let arr = [1,2,3,4];

let sum = arr.reduce((acc, val) => {
  return acc + val;
});

// sum = 10

  • 배열에서 문자열로

  • 이름 함쳐서 문자열로 출력 시키기


let users = [
  
  {name:"john",age : 20 },
  {name:"tim",age :40 },
  {name:"esther",age : 60 },
  
];

// "john, tim, esther" 이렇게 만들것이다. 

function sumName(retName , cuur ) {
	// 1. " " + "john" + ","
	// 2. "john," + "tim" + ","
	// 3. "john, time," + "esther" + ","
	retName = retName + cuur.name + ","; 
	return retName ; // 리턴을 꼭 해줘야 한다.
 }
 
 
users.reduce(sumName, ""); // 두번째 인자값에 초기값인  "" 넣어준다.

// "john,tim,esther,"




  • 배열에서 객체로

  • 첫번째 글자를 따서 전화번호부 만들기


// 원본
let users = [
  
  {name:"john",age : 20 },
  {name:"tim",age :40 },
  {name:"esther",age : 60 },
  
];

// 결과 출력 

let addressBook = {
	j : [
		{name:"john",age : 20 }
      ],
	t : [
		{name:"tim",age :40 }
      ],
	e : [
		{name:"esther",age : 60 }
 	  ]
};



//1. makeAddressBook < callback 함수를 미리 만든다. 

function makeAddressBook (addressBook, user) {
  // 첫번째 글자를 먼저 변수에 저장한다. 
  let firstLetter = user.name[0];
  
  // addressBook { };
  
  
  if (firstLetter in addressBook) {
	  // 만약 키가 있으면 해당 배열에 사람을 추가한다. 
    addressBook[firstLetter].push(user);
	} else {
	  // 만약 키가 없다면 해당 배열을 만들고
	  addressBook[firstLetter] = [];
	  // 사람을 추가한다. 
  	addressBook[firstLetter].push(user);
  }
	return addressBook; // 객체를 리턴한다. 
}

users.reduce(makeAddressBook, {} ); 

// {j: Array(1), t: Array(1), e: Array(1)}

/* 결과값 
{
	j : [
		{name:"john",age : 20 }
      ],
	t : [
		{name:"tim",age :40 }
      ],
	e : [
		{name:"esther",age : 60 }
 	  ]
};
*/

  • Using the reduce() method, how would you sum up the population of every country

  • data


let data = [
  {
    country: 'China',
    pop: 1409517397,
  },
  {
    country: 'India',
    pop: 1339180127,
  },
  {
    country: 'USA',
    pop: 324459463,
  },
  {
    country: 'Indonesia',
    pop: 263991379,
  }
]

  • Soultion



let sum = data.reduce(function(acc,val){
	
	return acc + val.pop;
		
	},0);
	
//1409517397 +1339180127 + 324459463 + 263991379 = 3337148366

// sum // 3337148366
  • except China?

let sum = data.reduce((acc, val) => {
  return val.country === 'China' ? acc : acc + val.pop;
}, 0);


//sum = 1927630969

How to convert a str of nums to an arr of nums?

  • Qeustion

  • str = “1,2,3,4” => [1, 2, 3, 4]


 
var a = "1,2,3,4";
var b = a.split(',');
/// ["1", "2", "3", "4"]

// how to make this : [1, 2, 3, 4] 

  • Soultion

  • useing Array.map to convert each element into a number.

var a = "1,2,3,4";

var b = a.split(',').map(function(item) {
    return parseInt(item, 10);
});

// b = [1, 2, 3, 4] 

  • useing Map and Number
var b = a.split(',').map(Number);

// b = [1, 2, 3, 4] 

  • useing from()

var b = Array.from(a.split(','),Number);

// b = [1, 2, 3, 4]

forEach(), map(), fliter()

    1. forEach()

array.forEach (callback(callbackFunction(element, index, array)

  • 배열 혹은 함수를 반복할때 사용

  • 리턴값 없다

  • ex)

  • forEach 로 배열의 합 구하기


function test(){
    var testArray = [1,2,3,4,5];
    var sum = 0;
    function getSum(value){
        sum =  sum + value;
    }
    testArray.forEach(getSum); // forEach(getSum) that's all  
    console.log(sum);
  }

test()  // 15 

  • 2.map()

array.map(callbackFunction(element, index, array)

  • immutable

  • 새로운 배열을 만들때 사용

  • 리턴값 있다.

  • ex)

  • for 문으로 name 값 가져오기

let users = [
  
  {name:"john",age : 20 },
  {name:"tim",age :40 },
  {name:"esther",age : 60 },
  
];


let userName = [];


for (let i = 0; i < users.length; i ++ ) {
	userName.push(users[i].name);
 }
 
 userName // ["john", "tim", "esther"]

  • map() 으로 name 값 가져오기

let users = [
  
  {name:"john",age : 20 },
  {name:"tim",age :40 },
  {name:"esther",age : 60 },
  
];


function getName (user){
  return user.name; //  리턴값 필요하다. 

}

users.map(getName); // ["john", "tim", "esther"]





  • 3.fliter()

array.fliter(callbackFunction(element, index, array)

  • 조건에 해당한 것을 새로운 배열의 형태로 출력 한다.

  • 리턴값 있다.

  • map 함수는 filter함수와 같이 오브젝트도 컨트롤 할 수도 있습니다.

  • 예제

  • filter 로 30 살 보다 많은 사람 사람을 찾는다


let users = [
  
  {name:"john",age : 20 },
  {name:"tim",age :40 },
  {name:"esther",age : 60 },
  
];

function getOldName(user){
	return user.age > 30; // 리턴 필요하다. 
}
// 그리고 filter 에 함수를 넣는다. 
users.filter(getOldName) // [{name:"tim",age :40 },{name:"esther",age : 60 }];
  • filter 로 이름에 s 가 있는 사람을 가져오고 싶다.?

let users = [
  
  {name:"john",age : 20 },
  {name:"tim",age :40 },
  {name:"esther",age : 60 },
  
];


function userIncludeS (user){
	return user.name.indexOf("s") !== -1; // 조건문 

 }
 
 
users.filter(userIncludeS) // [{name:"esther",age : 60 }];

sort()

arr.sort(sortfunc)

mutable

1.배열을 정렬한다.

2.알파벳 순서로 정렬한다.

3.숫자의 경우 암시적으로 문자열로 형변환 하기 때문에 숫자 1이 숫자 10보다 먼저 나온다.

4.sortfunc 로 비교 대상인 두개의 인자를 전달하는데, 리턴 값에 따라서 선후를 판단한다.


strArr = ["all", "before", "hello", "world"]

// a 가 크면 리턴 1  작은수부터 정렬
strArr.sort(function(a,b){
	if (a > b) {
	return 1;
} else if (a === b){
	return 0;
} else {
	return -1;
}
})


// a 가 작으면 리턴  큰수부터 정렬

strArr.sort(function(a,b){
	if (a > b) {
	return -1;
} else if (a === b){
	return 0;
} else {
	return 1;
}
})




Example 1


var numbers = [9,8,7,6,5,4,3,2,1];
alert(numbers.sort()); // array, [1,2,3,4,5,6,7,8,9]
alert(numbers); // array, [1,2,3,4,5,6,7,8,9], 원본을 변경한다. 
alert(numbers.sort() === numbers); // boolean, true, 원본과 반환값이 같다.
 
var numbers = [20, 10, 9,8,7,6,5,4,3,2,1];
//array, [1,10,2,20,3,4,5,6,7,8,9], 암시적으로 원소를 문자로 형변환 하기 때문에 10이 1뒤에 온다.
alert(numbers.sort()); 

Example 2

var numbers = [20, 10, 9,8,7,6,5,4,3,2,1];
var x = function(a,b){
	return a-b;
}

console.log(numbers.sort(x));

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20]


순서반대 로 할려면
return a+b;

[20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Example 3


function sortNumber(a,b){
// 비교 대상인 a와 b가 인자로 전달된다.
//alert('a :'+a+', b:'+b);
// a에서 b를 뺀 결과가 음수면 a가 b보다 작고, 0이면 같다.
// sort메소드는 return 값이 음수,양수,0인지에 따라서 순서를 정한다.
return a-b;
}
var numbers = [20, 10, 9,8,7,6,5,4,3,2,1];
alert(numbers.sort(sortNumber)); // array, [1,2,3,4,5,6,7,8,9,10,20]


Description from others


위의 sort함수를 보면 parameter로 function이 올수 있다은건 이 문서를 보고 알수 있습니다.
그런데 sort함수 parameter인 function의 parameter와 retrun에 대한 설명(?)은 어떻게 알수 있나요??

예를들어서
var numbers = [20, 10, 9,8,7,6,5,4,3,2,1]; 
function sortNumber(a,b){
return a - b;
}

이럴때, sortNumber함수(내가 만들려는 함수 )의 파라미터가 2개 (a,b)인건 어찌 알수있고, 
return함수가 어떻게 동작하는지는 어떻게 알수 있을까요?


Description from others


우선 [20, 10, 9,8,7,6,5,4,3,2,1] 배열에서 a-b라는 연산을 모두  다음 
 결과값으로 정렬하는 것이 결코 아닙니다.
뭐하러 굳이 뺄셈을 하고  값으로  정렬하겠습니까? 

자바스크립트의 정확한 알고리즘은 아니지만 
쉽게 정렬 알고리즘을 설명하면 이렇습니다. 

(a,b) 형식으로 지정한  인자를 차례로 비교합니다.

우선 배열 numbers[0] numbers[1] , 20 10 비교해 볼까요?
20-10 = 10 
결과값이 10 , 양수입니다.
sort함수에 sortNumber(a,b) return 값으로 양수 10 전달합니다. 
그럼 sort함수가 양수값을 전달받고 배열의 순서를 바꾸어 버립니다. 
(정확하게 말하면  배열 안에  값을 교체)
그럼 배열이 [10, 20, 9,8,7,6,5,4,3,2,1] 이렇게 바뀝니다. 

 다음 numbers[0] numbers[2]  10 9 비교합니다. 10 - 9 = 1 >0, 양수입니다. 
결과값이 양수이므로  10 9 순서를 바꿉니다. 
이런 식으로 계속  인자를 비교해서 결과값이 양수가 나오면 순서를 바꾸고, 
음수가 나오면 순서를 그대로 유지하는 겁니다.

배열이 바뀌어가는 순서를 보면 이해하기 쉽습니다.

[(20), (10), 9,8,7,6,5,4,3,2,1] 20-10 = 10,  양수이므로 순서바뀜! () 비교되는 인자값.
[(10), 20, (9),8,7,6,5,4,3,2,1] 10 - 9 = 1  양수, 순서 바뀜.
[(9), 20, 10, (8),7,6,5,4,3,2,1] 반복...
[(8), 20, 10, 9,(7)...]
...
[(2). 20, 10...3, (1)]
[(1), 20, 10...]

그럼 배열 내에서 가장 작은  1 찾아지겠죠. 

[1, 20, 10, 9,8,7,6,5,4,3,2]

1 순서는 바뀌지 않습니다. 1-2 = -1 
 결과값이 음수이기 때문이죠. 

 다음은 두번째 배열 차례입니다.
20 - 10 = 10 > 0 이므로 순서를  바꿉니다. 

[1, (20), (10), 9,8,7,6,5,4,3,2]
[1, (10), 20, (9), 8...]
[1, (9), 20, 10, (8)...]

이런 식으로 반복하다 보면 두번째로 작은  2 찾게 됩니다. 

....

[1, 2, 20, 10, 9,8,7,6,5,4,3]

그럼 다음은 세번째... 
이렇게 지루하게 반복하면 결국 정렬이 됩니다.

물론 실제 자바스크립트에서는 비교하는 순서가 다릅니다. 
다른 알고리즘을 쓰기 때문이죠.

이렇게 차례차례 비교해 나가면 인간이 이해하기는 쉽지만 
연산량이 기하급수적으로 늘어나기 때문에 다른 정렬 알고리즘을 쓰는 것이죠.

실제로는 
[20, 10, 9,8,7,6,5,4,3,2,1]
배열의 양쪽 끝부터 비교하고 (20, 1), 
 다음 배열의 가운데 값을 차례로 비교해 나갑니다. (1,6)
디버깅해 보시면 쉽게 아실  있을 겁니다

Description from others

ar numbers = [20, 10, 9,8,7,6,5,4,3,2,1]; 
function sortNumber(a,b){
return a - b;
}
 하게 되면 모든 값들끼리 a - b를 하게 됩니다. 

그렇게 나온 값들을 sort() 넣으면, (a - b) 순서가 숫자가 낮은 것부터 높은 순서대로 정렬이 되겠죠.
-19(1 - 20), -9(1-10), -8(1-9), -7(1-8), -6(1-7), -5(1-6), -4(1-5), -3(1-4), -2(1-3), -1(1-2)
-18(2-20), -8(2-10), -7(2-9), -6(2-8), -5(2-7), -4(2-6), -3(2-5), -2(2-4), -1(2-3), 0(2-2), 1(2-1)
-17(3-20), -7(3-10), -6(3-9), -5(3-8), -4(3-7), -3(3-6), -2(3-5), -1(3-4), 0(3-3), 1(3-2), 2(3-1)
...
10(20-10), 11(20-9), 12(20-8), 13(20-7), 14(20-6), 15(20-5), 16(20-4), 17(20-3), 18(20-2), 19(20-1)

그럼 계산된 숫자의 크기에 따라서 a와 b의 순서가 sort() 의해 재배열 되어
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20
 나옵니다.

# every() 와 some()

  • 1.every()

array.every(callbackFunction(currentValue, index, array), thisArg)

  • every 함수는 배열의 모든 요소가 callbackFunction 에서 true를 리턴해야 true를 리턴, 하나라도 false가 떨어지면 false를 리턴합니다.

  • every나 some 함수의 경우 배열내 값이 존재하는지 확인할때나 조건에 맞는(혹은 맞지 않는) 값이 있는지 확인 할 때 등 활용이 가능합니다.

  • 2.some()

array.some(callbackFunction(currentValue, index, array), thisArg)

  • some 함수는 배열의 요소 중 하나라도 callbackFunction에서 true를 리턴하면 true를 리턴 합니다.

  • every나 some 함수의 경우 배열내 값이 존재하는지 확인할때나 조건에 맞는(혹은 맞지 않는) 값이 있는지 확인 할 때 등 활용이 가능합니다.

  • every 와 some 의 차이점

every 와 some 메서드는 배열을 순회하면서 특정 조건을 배열의 값들이 만족시키는지 검사하는 메서드로서 호출한 배열이 결론적으로 조건을 만족시키는지(true), 만족시키지 못하는지(false)를 알려준다. every 와 some 의 차이는 every 가 배열의 모든 값이 조건을 만족해야, some 은 일부만 만족해도 true 를 return 한다

————————————————————-

2. Dom

————————————————————-

Dom 이란 ?


// Dom을 이용해서 HTML문서를 제어할수 있다

// DOM 객체의 값 바꾸기

// ex1-1 document.getElementsByTagName()




document.getElementsByTagName() 
>>html에 있는 tag name  가져오는 명령이다.

var list = document.getElementsByTagName('h2') 
>>모든 h2를 list 라는 변수에 담아오겠다. 

태그 이름을 바꾸기 위해서는 

a
>> [h2,h2]

a[0]
>> <h2>hello 1</h2>

a[1]
>> <h2>hello 2</h2>
이렇게 배열안에 들어가 있다. 

a[1].innerHTML = "good morning"
heelo 2 >> good morning 으로 바뀐다. 

이것이 dom  역활 이다. 



// ex1-2 document.getElementsById()


var a = document.getElementsById("main")
>> main 아이디 값의 tag를 가져와서  a 변수에 담는다

a
>> <p id = main>hello jj </p>

a.innerHTML = "hello John jung"

a

>><p id = main>hello john jung</p>

버튼 만들기

<body>
    <h1>함수를 이용해 버튼 만들기</h1>
    
    
    // 1.value 를 지정하기 in HTML
    
    
    <input id = "input1" type ="text">
    <button id ="button1">cilck</button>
    
    
    <script>
    
    // 2. 함수&변수를 만들어서 준비한다 
    
        var ret = function(){
            document.getElementById("input1");
            console.log(input1.value);
        }
    
        var button = document.getElementById("button1");
        
        
    // 3 .입력받을 ID 값을 받는 함수를 연결해준다.
       
        button1.onclick = ret; 

    /script>
    


</body>

e.target 이란 ?

  • event.target 와 event.target.parentNode 차이점

* e.target === 클릭된애
* e.target.parentNode === 클릭된애 부모태그 
* e.target.parentNode.parentNode === 클릭된애 부모의 부모태그

  • event.target 과 currentTarget 의 차이점

* event.target  마우스 클릭할때 발생되는 이벤트가 일어나는 곳을 말하고
* event.currentTarget  addEventListener 를발생시키는 대상 

# How to check if element has any children ?


if (element.firstChild) {
    // It has at least one
}

if (element.hasChildNodes()) {
    // It has at least one
}

if (element.childNodes.length > 0) { // Or just `if (element.childNodes.length)`
    // It has at least one
}

if (element.children.length > 0) { // Or just `if (element.children.length)`
    // It has at least one element as a child
}

if (element.firstElementChild) {
    // It has at least one element as a child
}

var hasChildElements, child;
hasChildElements = false;
for (child = element.firstChild; child; child = child.nextSibling) {
    if (child.nodeType == 1) { // 1 == Element
        hasChildElements = true;
        break;
    }
}

function hasChildElement(elm) {
    var child, rv;

    if (elm.children) {
        // Supports `children`
        rv = elm.children.length !== 0;
    } else {
        // The hard way...
        rv = false;
        for (child = element.firstChild; !rv && child; child = child.nextSibling) {
            if (child.nodeType == 1) { // 1 == Element
                rv = true;
            }
        }
    }
    return rv;
}




checkbox 안에 있는 value 값 얻기

  • html


<div class = "container">
    
    <input type="checkbox" class ="checks" value ="뜨거워"> hot
    <input type="checkbox" class ="checks" value ="추워"> clod
    <a href="#" onclick="submitFun();return false;">ok </a>

</div>

  • js



	function submitFun() {
		

		var checks = document.getElementsByClassName('checks')
		var str = "";
		

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

			if (checks[i].checked === true ) {
 				str += checks[i].value + "";
 			}
 		}
 		alert(str);
	}

버튼 엔터키 작동 및 입력창 커서유지시키기



<h1>this is coffee machine<h1>
<div id = "menu">menu</div>
<input id = "input" type="text" placeholder = "what drink?">
<button id = "btn">order</button>
<ol id = "list">
  <li class = "americano">americano</li>
  <li class = "latte">latte</li>
  <li class = "flatWhite">flatWhite</li>
<ol>

 
// 버튼을 누르면 list 가 추가되는데 사용자를 위하여 엔터로 control 할수 있게 하고 커서가 계속 입력창에 깜빡이게 하는 방법이다. 

let coffeeList = document.querySelector("#list");
let coffeeInput = document.querySelector("#input");
let add = document.querySelector("#btn");
// form tag를 만들어 input 과 btn tags 를 넣는다.  
  let form = document.createElement("form");
  document.body.appendChild(form);
  form.appendChild(coffeeInput);
  form.appendChild(add);

// form tag에 이벤트를 발생시킨다. 
// form 과 "submit" 의 기본동작은 엔터를 첬을때 새로고침 or 다른페이지로 넘어가게 되어있다. 
// 그것을 막기 위해서 function(event) 설정하고  event.preventDefalut() 넣어주면 된다. 

form.addEventListener('submit',function(event){
    event.preventDefault();
  let newList = document.createElement("li");  
  newList.setAttribute("class","new-list");
  coffeeList.appendChild(newList);
  newList.textContent = coffeeInput.value;
  coffeeInput.focus(); // input tag 에 함수를 넣는다. 입력후 계속 입력할수 있게 해준다. 
  
})




addEventListener 사용하기

<h1>this is coffee machine<h1>
<div id = "menu">menu</div>
<input id = "input" type="text" placeholder = "what drink?">
<button id = "btn">order</button>
<ol id = "list">
  <li class = "americano">americano</li>
  <li class = "latte">latte</li>
  <li class = "flatWhite">flatWhite</li>
<ol>



// 1. addEventListener
// 버튼을 누르면 menu 버튼이 한글로 바뀜

let xxx = document.querySelector("#btn");
let menu = document.querySelector("#menu");

xxx.addEventListener('click', function(){
  menu.innerHTML = "메뉴";
})

// 2 addEventListener 
// 버튼 누르면 리스트가 추가된다. 

let coffeeList = document.querySelector("#list");
let coffeeInput = document.querySelector("#input");
let add = document.querySelector("#btn");

add.addEventListener('click',function(){
  let newList = document.createElement("li")
  newList.setAttribute("class","new-list");
  coffeeList.appendChild(newList);
  newList.textContent = coffeeInput.value;
})



# e.target 와 e.target.parentNode or currentTarget의 차이점


* e.target === 클릭된애
* e.target.parentNode === 클릭된애 부모태그 
* e.target.parentNode.parentNode === 클릭된애 부모의 부모태그

# event.target 과 currentTarget 의 차이점


* event.target  마우스 클릭할때 발생되는 이벤트가 일어나는 곳을 말하고
* event.currentTarget  addEventListener 를발생시키는 대상 

버튼 엔터키 작동 및 입력창 커서유지시키기



<h1>this is coffee machine<h1>
<div id = "menu">menu</div>
<input id = "input" type="text" placeholder = "what drink?">
<button id = "btn">order</button>
<ol id = "list">
  <li class = "americano">americano</li>
  <li class = "latte">latte</li>
  <li class = "flatWhite">flatWhite</li>
<ol>

 
// 버튼을 누르면 list 가 추가되는데 사용자를 위하여 엔터로 control 할수 있게 하고 커서가 계속 입력창에 깜빡이게 하는 방법이다. 

let coffeeList = document.querySelector("#list");
let coffeeInput = document.querySelector("#input");
let add = document.querySelector("#btn");
// form tag를 만들어 input 과 btn tags 를 넣는다.  
  let form = document.createElement("form");
  document.body.appendChild(form);
  form.appendChild(coffeeInput);
  form.appendChild(add);

// form tag에 이벤트를 발생시킨다. 
// form 과 "submit" 의 기본동작은 엔터를 첬을때 새로고침 or 다른페이지로 넘어가게 되어있다. 
// 그것을 막기 위해서 function(event) 설정하고  event.preventDefalut() 넣어주면 된다. 

form.addEventListener('submit',function(event){
    event.preventDefault();
  let newList = document.createElement("li");  
  newList.setAttribute("class","new-list");
  coffeeList.appendChild(newList);
  newList.textContent = coffeeInput.value;
  coffeeInput.focus(); // input tag 에 함수를 넣는다. 입력후 계속 입력할수 있게 해준다. 
  
})




onclick 동작하는 원리



<h1>this is coffee machine<h1>
<div id = "menu">menu</div>
<input id = "input" type="text" placeholder = "what drink?">
<button id = "btn">order</button>
<ol id = "list">
  <li class = "americano">americano</li>
  <li class = "latte">latte</li>
  <li class = "flatWhite">flatWhite</li>
<ol>

// 1. onlick 동작하는원리 
// menu 버튼을 누르면 menu 가 red 로 변함  

let xxx = document.querySelector("#btn");

xxx.onclick = function() {
  document.querySelector("#menu").style.background="red";
}


textContent 와 value 의 차이점


tag 안에 들어가는 글자내용은  textcontent 이고
input 안에 들어가있는 글자내용은 value 이다 


버튼누르면 새로운 글 추가

  • HTML


  <button id="clickbtn">new_tweet</button>
    
    <div id="comments"></div>
 

  • JS


var DATA = [
  { user: 'ingikim', message: 'Welcome to Code States #codestates', created_at: '2019-01-03 12:30:20' },
  { user: 'satya', message: 'this is test message #pair #programming', created_at: '2019-01-04 18:30:20' },
  { user: 'sundar', message: 'code now! #work #hard', created_at: '2019-01-05 07:30:20' },
  { user: 'steve', message: 'Stay hungry, and stay foolish', created_at: '2015-01-03 12:30:20' },
  { user: 'tim', message: 'education for real world', created_at: '2019-01-04 18:30:20' }
];

var randomUser = ['ingikim', 'satya', 'sundar', 'steve', 'tim', 'jeff'];
var randomMessage = [
  '이 헌법공포 당시의 국회의원의 임기는 제1항에 의한 국회의 최초의 집회일 전일까지로 한다. 감사원은 원장을 포함한 5인 이상 11인 이하의 감사위원으로 구성한다.',
  '헌법재판소의 조직과 운영 기타 필요한 사항은 법률로 정한다. 모든 국민은 자기의 행위가 아닌 친족의 행위로 인하여 불이익한 처우를 받지 아니한다.',
  '헌법개정은 국회재적의원 과반수 또는 대통령의 발의로 제안된다. 국가는 재해를 예방하고 그 위험으로부터 국민을 보호하기 위하여 노력하여야 한다.',
  '모든 국민은 직업선택의 자유를 가진다. 군인은 현역을 면한 후가 아니면 국무총리로 임명될 수 없다. 행정권은 대통령을 수반으로 하는 정부에 속한다.',
  '민주평화통일자문회의의 조직·직무범위 기타 필요한 사항은 법률로 정한다. 국가는 농·어민과 중소기업의 자조조직을 육성하여야 하며, 그 자율적 활동과 발전을 보장한다.',
  '국회는 국정을 감사하거나 특정한 국정사안에 대하여 조사할 수 있으며, 이에 필요한 서류의 제출 또는 증인의 출석과 증언이나 의견의 진술을 요구할 수 있다.',
  '인간이 얼음에 고행을 따뜻한 가장 이것이다. 꽃이 곧 동력은 끝에 동산에는 그것은 거선의 별과 인생의 것이다. 구하지 착목한는 스며들어 인생의 것이다.',
  '새 가슴에 있는 만천하의 있다. 몸이 뜨거운지라, 청춘의 소리다.이것은 같으며, 피다. 설산에서 힘차게 옷을 피다. 놀이 그들의 인간의 주는 소금이라',
  '귀는 우리는 피에 무엇이 이것이다. 구하지 우리는 그들은 약동하다. 따뜻한 발휘하기 사람은 충분히 사막이다.'
]

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}

function generateNewTweet() {
  var tweet = {};
  tweet.user = randomUser[getRandomInt(0, randomUser.length)];
  tweet.message = randomMessage[getRandomInt(0, randomMessage.length)];
  tweet.created_at = new Date().format(); // 어떻게 하면 보기 좋은 형태로 나타낼 수 있을까요?
  return tweet;
}

Number.prototype.padLeft = function() {
  if(this < 10) {
    return '0' + String(this);
  }
  else {
    return String(this);
  }
}

Date.prototype.format = function() {
  var yyyy = this.getFullYear();
  var month = (this.getMonth() + 1).padLeft();
  var dd = this.getDate().padLeft();
  var HH = this.getHours().padLeft();
  var mm = this.getMinutes().padLeft();
  var ss = this.getSeconds().padLeft();

  var format = [yyyy, month, dd].join('-') + ' ' + [HH, mm, ss].join(':');
  return format;
}





//2.check_new_tweet! 
function myFunction() {
    let  array = [];
    let obj = generateNewTweet();

    array.push("<div class='comment'>"
         + "<div class='username'>"  + obj.user + "</div>" 
         + "<div>" + obj.message + "</div>"
         + "<div>" + obj.created_at + "</div>"
         + "</div>");

    
  comments.innerHTML = array + comments.innerHTML;

}




let Button = document.querySelector('#clickbtn');

function randomTweet() {
    clickbtn.onclick = function() {
        myFunction();
    }
}

randomTweet();





script 위치



//Html 파일에서 script 를 head 안에 넣으면 script 안에 써있는 코드들이 실행이 안된다 !

//하지만 script 안에 있는 코드들을 실행 시키려면 


window.onload = function () { } // 실행하고싶은 코드넣으면 실행할수 있다. 



insertBefore()


// html

<h1>test</h1> 
  
<ul id="subjects"> 
        <li>C</li> 
        <li>Python</li> 
</ul> 
  
  
// js

  <script>
  
  function myGeeks() { 
            var newItem = document.createElement("li"); 
            var textnode = document.createTextNode("Java"); 
            newItem.appendChild(textnode); 
  
            var list = document.getElementById("subjects"); 
            list.insertBefore(newItem, list.childNodes.lastChild); // 마지막으로 삽입하고 싶으면 lastChild
            
            list.insertBefore(newItem, list.childNodes[0]); //  첫번째로 삽입하고 싶으면 [0] 
            } 

 myGeeks();
  
  </script>

// html

// Java     // 삽입 되었다. 
// C
// Python





————————————————————-

3. Studying_Notes

————————————————————-

타이머 사용하기

  • setTimeout(callback, millisecond)

내가 설정한 시간 후에 함수를 실행;


setTimeout(function() {
  console.log('1초후 이것이 실행된다');
}, 1000);


  • setInterval(callback, millisecond)

내가 설정한 시간마다 계속 실행되는 함수


setInterval(function() {
  console.log('1초마다 실행');
}, 1000);


  • clearInterval(timerID)

반복 실행중인 타이머를 종료


let timer = setInterval(function() {
  console.log('1초마다 실행');
}, 1000);


clearInterval(timer); // 실행되는 순간 내가 만든 함수는 멈춘다. 

# 객체 숫자 계산 하는 방법

  • How to Count the Number of Properties of the JavaScript Object


// While working with JavaScript, I come across a requirement to count a number of properties in a JavaScript object. I found two ways to find the number of properties in an object. They are as follows:




Consider an object, "cat," as demonstrated below:

var cat = {
    name: 'foo',
    age: 9
}


// You can find a number of properties by iterating in a for loop and update counter, as shown in the below listing:

let count = 0;
for (var c in cat) {
    count = count + 1;
}
console.log(count);// 2

Above code will print “2” as the output.

The above approach not only prints the object’s own enumerable properties, but it also prints properties of objects to which it is linked. To further understand it, let us consider the below listing:

var animal = {
    canRun: true
}
var cat = {
    name: 'foo',
    age: 9
}
cat.__proto__ = animal;

There are two objects, cat andanimal, and the cat object is linked to an animal object using the proto property. Now, when you use a for loop to iterate and count a number of properties, it will also count the enumerable properties of the animal object. Therefore, the code listing below will print “3.”

var animal = {
    canRun: true
}
var cat = {
    name: 'foo',
    age: 9
}
cat.__proto__ = animal;
let count = 0;
for (var c in cat) {
    count = count + 1;
}
console.log(count);// 3

A JavaScript for loop will iterate through all the linked properties of the object.

To count the object’s own enumerable properties, you may consider using another approach, Object.keys(), which only enumerates the object’s own enumerable properties. It does not enumerate the object’s linked properties.

Moving forward, let us again consider the cat object which is linked to animal object and count the number of properties using Object.keys:


var animal = {
    canRun: true
}
var cat = {
    name: 'foo',
    age: 9
}
cat.__proto__ = animal;
var count = Object.keys(cat).length;
console.log(count);

Now you will get “2” printed as the output.

Object.keys only enumerates the object’s own enumerable properties.

If the object’s property enumerable is set to false, then it is not a member of the Object.keys array. Let us again consider the cat object and set its name property enumerable to false.

var cat = {
    name: 'foo',
    age: 9
}
Object.defineProperty(cat, 'name', { enumerable: false });

Now, when you use Object.keys to find a number of properties, it will count only one.

var count = Object.keys(cat).length;
console.log(count);  // print 1

In closing, these are the two ways that you can use to find the number of properties in a JavaScript object

# prototype를 사용해 ininstance 객체에 키값 속성값 추가하는법


// prototype를 사용해 모든 instance 객체에 property와 method 추가하는 법을 확인합니다

function objFunc(para) { // 객체를 담고있는 함수를 먼저 만든다.
      this.age = para; // key 는 name / property는 para  < 아직 모른다.
    }

    let newObj = new objFunc(33); // para 값이 33이 됨 따라서 info1 = { age:33 }
    newObj.name = "John"; //  // 함수안에 infor1 객체안에 키값이랑 property 를 추가한다.

newObj //>> objFunc = { age: 33 , name: "John" } name = "john" 이 추가됬다. 

// prototype 을 사용해서 추가하기

objFunc.prototype.text = function() { // 처음함수에 prototype을 넣는다.  그다음에 text라는 키값을 지정한다. 이키값은 함수이기도 하다. 그래서 키이면서도 함수인 text()가 실행되면 return값이 출력된다.  
	return "this is the stroy what I want to say to " + newObj.name; 
}

newObj.text(); // "this is the stroy what I want to say to john"


객체안에 담겨있는 function 사용하기


  // 객체를 만들고 속성값에 text 내용을 출력할 함수를 만든다. 
  
 // 이름을 몇번 집어넣을지 num 라는 것을 Array(num+1)를 통해 만들고 join 메소드를 이용해 " " 띄어쓰기를 한후 text 를 출력한다.

obj1 = {
      name1 : "john",
      name2: "tim",
      funcSum: function (num) {
        return "They are " + this.name1 + " and the" +
        Array(num + 1).join(" " + this.name2);     
      }
    };

let massage = obj1.funcSum(2) //  객체안에 있는 속성인 funcSum(2) 호출한다.

console.log(massage) // >> "They are john and the tim tim"

함수가 객체의 키값으로 사용


// 객체와 함수를 이용한다.
// 장점 객체안에 키값을 자유롭게 사용할수 있다.

let funcGood = function (elem) {
      return elem + " is good man!";
    };
    let obj1 = { name: funcGood };
    

obj1.name("John") // >> john is good man!

// 만약 obj.name 이 다른 기능을 가지고있는 함수를 대입하면..

let funcBad = function (elem) {
      return elem + " is good bad!";
    };

obj.name = funcBad 

// 기존에 있던 obj.name 기능은 사라지고 obj.name 의 기능은

obj.name("john") // john is good bad!


  • parameter 지정하는 법

// arguments 이용 

function getMax() {
  let max = arguments[0] 
  for (let i = 0; i < arguments.length; i ++ ) {
    if(max < arguments[i]) {
       max = arguments[i] 
    }
  }
   return max;
}

// args 이용

function getMax(a,b , ...args) {
  let max = args[0] 
  for (let i = 0; i < args.length; i ++ ) {
    if(max < args[i]) {
       max = args[i] 
    }
  }
   return max;
}




ES6


function timeToGoHome(distance, speed = 20 ) { 

	return distance + speed;
}

timeToGoHome(10);

// 30

timeToGoHome(10,10); // 두번째 값인 지정했던 speed 값이 변한다. 

// 20



 // 만약 첫번째 값을 지정하고 출력하고 싶다면

function timeToGoHome(distance = 20, speed) { 

timeToGoHome(undefined,20) ;
// 40
 

Making_GUID


JavaScript
Its easy to make GUIDs in JavaScript. Below is code to get strings that look like GUIDs. This code just random GUIDs they are not claimed to be unique. Don't use these if its very important.

function S4() {
    return (((1+Math.random())*0x10000)|0).toString(16).substring(1); 
}
 
// then to call it, plus stitch in '4' in the third group
guid = (S4() + S4() + "-" + S4() + "-4" + S4().substr(0,3) + "-" + S4() + "-" + S4() + S4() + S4()).toLowerCase();


할당 연산자

// 3 가지가 똑같은 것이다.  할당연산자

count = count + 1 
coutt+= 
count++

랜덤 숫자 원하는 수대로 뽑기


// for 문을 이용한 랜덤 숫자 원하는수대로 뽑기 
for ( let i = 0 ; i <= 30; i = i + 1 ) { 
  String(Math.random().toFixed(i).split('').slice(2).join('')) // slice(2) 를 이용해 0과 . 을 제거한 나머지 숫자들을 출력한다.  
}


랜덤글자 가져오기


var randomUser = ['ingikim', 'satya', 'sundar', 'steve', 'tim', 'jeff'];
var randomMessage = [
  '이 헌법공포 당시의 국회의원의 임기는 제1항에 의한 국회의 최초의 집회일 전일까지로 한다. 감사원은 원장을 포함한 5인 이상 11인 이하의 감사위원으로 구성한다.',
  '헌법재판소의 조직과 운영 기타 필요한 사항은 법률로 정한다. 모든 국민은 자기의 행위가 아닌 친족의 행위로 인하여 불이익한 처우를 받지 아니한다.',
  '헌법개정은 국회재적의원 과반수 또는 대통령의 발의로 제안된다. 국가는 재해를 예방하고 그 위험으로부터 국민을 보호하기 위하여 노력하여야 한다.',
  '모든 국민은 직업선택의 자유를 가진다. 군인은 현역을 면한 후가 아니면 국무총리로 임명될 수 없다. 행정권은 대통령을 수반으로 하는 정부에 속한다.',
  '민주평화통일자문회의의 조직·직무범위 기타 필요한 사항은 법률로 정한다. 국가는 농·어민과 중소기업의 자조조직을 육성하여야 하며, 그 자율적 활동과 발전을 보장한다.',
  '국회는 국정을 감사하거나 특정한 국정사안에 대하여 조사할 수 있으며, 이에 필요한 서류의 제출 또는 증인의 출석과 증언이나 의견의 진술을 요구할 수 있다.',
  '인간이 얼음에 고행을 따뜻한 가장 이것이다. 꽃이 곧 동력은 끝에 동산에는 그것은 거선의 별과 인생의 것이다. 구하지 착목한는 스며들어 인생의 것이다.',
  '새 가슴에 있는 만천하의 있다. 몸이 뜨거운지라, 청춘의 소리다.이것은 같으며, 피다. 설산에서 힘차게 옷을 피다. 놀이 그들의 인간의 주는 소금이라',
  '귀는 우리는 피에 무엇이 이것이다. 구하지 우리는 그들은 약동하다. 따뜻한 발휘하기 사람은 충분히 사막이다.'
]


// getRandomInt(min,max)  이용해 인자만큼 가져오는 방법


function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}


// 각각 user or message or time 을 객체안에 넣는다.
// 여기서 들어가는 요소들은 랜덤하게 들어가게 된다. 

function generateNewTweet() {
  var tweet = {};
  tweet.user = randomUser[getRandomInt(0, randomUser.length)]; 
  tweet.message = randomMessage[getRandomInt(0, randomMessage.length)];
  tweet.created_at = new Date().format(); 
  return tweet;
}


Get Current Data & Time in JS



var today = new Date(); // Data 가져온다. 
var date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate(); // 날짜
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); // 시간 

var dateTime = date+' '+time;  

dateTime // 2019-9-5 13:2:48"

block 스코프와 function 스코프의 차이


// block 스코프

for (let i = 0;  i < 5; i = i + 1) {
	console.log(i); //  0,1,2,3,4  출력된다. 
}

console.log(i) //  ReferenceError 출력 이유 : i라는 변수는 block let = i 선언되었을때 i 의 변수는  block 안에 제한 되기 때문이다.


// 
for (var i = 0;  i < 5; i = i + 1) {
	console.log(i); //  0,1,2,3,4  출력된다. 
}
console.log(i) // 5   이유: var 변수를 지정했을때 block의 범위를 넘어선다. 

var or let 변수를 사용한 함수중 어던것이 에러??

![](/tutorial/Javascript_Note_files/Screen Shot 2019-08-28 at 4.41.59 PM.png)


function greetSomeone (firstName ) { 
  let time = "night";
  
  if (time === "night") {         
    let greeting = "Good Night"; ////////// let greeting block 안에 갇혀 있다. 이 block 를 벗어나는 순간 효력을 잃는 다. 
  }
  
  
  return greeting + ' ' + firstName;  ///  greeting 실행되지 않는다 
}

greetSomeone('steve');

var and let and const

![](/tutorial/Javascript_Note_files/Screen Shot 2019-08-28 at 5.37.46 PM.png)

Strict Mode



// 변수를 안전하게 쓰기위한 “use strict”

`use strict` //  처음 시작에 이렇게 달아둔다.

function showAge() {
  arr = [1234];     //  선언되지 않는 변수가 실행되지 않게 해준다. 
console.log(arr);
}


다중배열 하나로 합치기

  • 재귀로 한 방법

function flatten(nestedArray, result) {


     // 재귀를 이용한것 

     result = [];
     function flatarr(nestedArray) {
       for(let i = 0; i < nestedArray.length; i++) {
         if(!Array.isArray(nestedArray[i])) {
           result = result.concat(nestedArray[i])
         } else {
           flatarr(nestedArray[i]);
         }
       }
     } flatarr(nestedArray);
     return result;
   };




  • for 문으로 한방법

function flatten(nestedArray) {
    //[1, [2], [3, [[[4]]]]]
    //oneflat([1, [2], [3, [[[4]]]]])
    // result = [1, 2, 3, [[[4]]]]
    // result = [1, 2, 3, 4]
    let oneflat = function(array) {
      let resultArr = []
      for (let i in array) {
        if (Array.isArray(array[i])) {
          resultArr = resultArr.concat(array[i]);
        } else {
          resultArr.push(array[i]);
        }
      }
      return resultArr;
    }
    let isinArr = function(array) {
      for (let i in array) {
        if (Array.isArray(array[i])) {
          return true;
        }
      }
      return false;
    }
    while(isinArr(nestedArray)) {
      nestedArray = oneflat(nestedArray);
    }
    return nestedArray;
  };





  • flat(Infinity)

arr = [1, [2], [3, [[[4]]]]]

arr.flat(Infinity)

/// [1,2,3,4]


function flatten(nestedArray, result) {

   let arr = [];
  let arr2 = [];
  if(Array.isArray(nestedArray)) {
    arr = nestedArray.join().split(',');
  }
  for(let i=0; i < arr.length; i++) {
    arr2.push(Number(arr[i]));
  }
  return arr2;
};

flatten([1, [2], [3, [[[4]]]]]) // 

두개의 배열을 비교 및 출력

  • filter() and indexOf()

let filtered1 = [1, 2, 3, 4, 5, 12]
let filtered2 = [1, 2, 4, 8]

let result = filtered1.filter(function(val) {
  return filtered2.indexOf(val) !== -1;
  
reulst // [1, 2, 4] 중복된 값을 리턴한다. 
});

  • filter() and includes()

let filtered1 = [1, 2, 3, 4, 5, 12]
let filtered2 = [1, 2, 4, 8]

let result = filtered1.filter((val) => {
  return filtered2.includes(val);

})

result  // [1, 2, 4]

underBar


(function() {
  'use strict';

  window._ = {};

  // argument로 무엇이 전달되든간에, 있는 그대로 리턴하세요.
  // 이 함수가 쓸데없어 보일지 모르겠지만, 기억하세요! - 만약 함수에 iterator가 필요하고,
  // 뭐라도 넘겨줘야 하는 상황에는 이 함수가 유용할 것입니다.
  _.identity = function(val) {
    return val;
  };

  /**
  * COLLECTIONS
  * ===========
  *
  * 이 섹션에서는 우리는 collection이라고 불리는 값들의 집합을 이용하는 함수에 집중할겁니다.
  * JavaScript에서는 collection은 값들을 포함하며, 배열 혹은 객체가 될 수 있습니다.
  *
  *
  * IMPORTANT NOTE!
  * ===========
  *
  * .first 함수가 이미 구현되어 있습니다. 이 함수를 가이드 삼아, 앞으로 나올 함수들을 구현해보세요.
  * 사전에 이미 완료된 과제의 일부분을 만나게 될 경우, 반드시 코드를 잘 읽어보고 이해하고 넘어가십시오.
  * 이러한 과정을 지나친다면, 앞으로 구현하게 될 함수가 훨씬 더 어렵게 느껴질겁니다.
  */

  // 배열의 처음 n개의 element를 담은 배열을 리턴하세요.
  // 만일 n이 undefined일 경우, 단순히 첫번째 element를 리턴하세요.
  _.first = function(array, n) {
    return n === undefined ? array[0] : array.slice(0, n);
  };

  // first와 비슷하게, 마지막 n개의 element를 담은 배열을 리턴하세요.
  // 만일 n이 undefined일 경우, 단순히 마지막 element를 리턴하세요.
  _.last = function(array, n) {
      if ( n===0 ) {
        return [];
      }
      return n === undefined ? array.slice(-1).pop() : array.slice(-n);
  
    };
  // iterator(value, key, collection)를 collection의 각각의 key-value pair에 대해 호출하세요.
  // iterator는 함수로 전달되며, 쉽게 말해 반복해서 실행하는 함수입니다.
  // collection으로 배열과 객체를 다 받을 수 있어야 합니다.
  // 참고로 배열의 value는 element이며, key는 index입니다.
  //
  // Note: _.each 는 아무런 값도 리턴하지 않습니다.
  // 다만 단순히 iterator 함수를 전달되는 collection의 각 항목에 대해 실행할 뿐입니다.
  //
  // Note 2: 이 문제를 풀기 위해서는 여러분이 spec 디렉토리에 있는 테스트 케이스의 요구사항을 잘 살펴볼 필요가 있습니다.
  // 실제로 어떻게 사용되는지 각 테스트 케이스 항목에 잘 나와 있습니다.
  _.each = function(collection, iterator) {
    if (Array.isArray(collection)) {
      for (let i = 0; i < collection.length; i++) {
        // iterator(value, key, collection)
        iterator(collection[i], i, collection);
      }
    } else {
      for (let key in collection) {
        iterator(collection[key], key, collection);
      }
    }
  };

  // target으로 전달되는 값이 array에서 발견되면, 그 index를 리턴하세요.
  // 만일 array에서 발견할 수 없다면 -1을 리턴하세요.
  _.indexOf = function(array, target) {
    // TIP: Here's an example of a function that needs to iterate, which we've
    // implemented for you. Instead of using a standard `for` loop, though,
    // it uses the iteration helper `each`, which you will need to write.
    var result = -1;

    _.each(array, function(item, index) {
      if (item === target && result === -1) {
        result = index;
      }
    });

    return result;
  };

  // 테스트 함수를 통과하는 모든 element를 담은 배열을 리턴하세요.
  _.filter = function(collection, test) {

    let result = [];
    for (let i = 0; i < collection.length; i ++  ) {
      if (test(collection[i])) {
       result.push(collection[i]);
      }

    }
  return result;
  
  }

  // 테스트 함수를 통과하지 않는 모든 element를 담은 배열을 리턴하세요.
  _.reject = function(collection, test) {
    // TIP: see if you can re-use _.filter() here, without simply
    // copying code in and modifying it

    let result = [];
    for (let i = 0; i < collection.length; i ++  ) {
      if (!test(collection[i])) {
        result.push(collection[i]);
      }
    }

    return result;
  };

  // element가 중복되지 않는 새로운 array를 만드세요.
  _.uniq = function(array) {


    // 1. Array new Set
    
    // let newArr = array.slice(); // 복제 하고 
    // let result = new Set(newArr); // obj 로 바뀐다. 바뀌는 이유는?

    // return [...result];
    // } 

    // // return [result] //  실행되지 않는다.  이유는 obj으로 출력되기 때문.


    
    
    // 2 Array.from() 

    return Array.from(new Set(array));
    }



    // 3.reduce() xxx 값은 출력되는데 데스트 통과는 못함
       
    // array.reduce(function(unique, item){
    //     if (unique.includes(item)){
    //     return unique;
    //       } else {
    //     return [...unique,item];
    //     }
    //   },[]);


    // }


      // const array = ['0', 1, 2, '0', '0', 3];
      // array.reduce((unique, item) => {
      //   console.log(
      //     // a. Item
      //     item,
      //     // b. Final Array (Accumulator)
      //     unique,
      //     // c. 조건(이 조건이 false여야만 값이 푸시된다
      //     unique.includes(item),
      //     // d. Reduce Function Result
      //     unique.includes(item) ? unique : [...unique, item],
      //   );
      //   return unique.includes(item) ? unique : [...unique, item]
      // }, []); // 초기 Accumulator 는 빈 array 이다
      // }

  // iterator를 각 element에 적용한 결과를 담은 새로운 array를 리턴하세요.

  _.map = function(collection, iterator) {
    // map() is a useful primitive iteration function that works a lot
    // like each(), but in addition to running the operation on all
    // the members, it also maintains an array of results.

// collection.map(iterator(value, key, collection)){
    let newArr = [];  
  
      for (let i = 0; i < collection.length; i ++ ){
        newArr.push(iterator(collection[i]));
      } 
      return newArr;
  }

  // 객체의 배열을 가져와서, 그 안에 있는 특정 속성의 값의 배열을 리턴하세요.
  // 예를 들어, people이라는 객체가 담긴 배열을 가져와서, 그들의 나이만 리턴할 수 있어야 합니다.


  _.pluck = function(collection, key) {
    // TIP: map is really handy when you want to transform an array of
    // values into a new array of values. _.pluck() is solved for you
    // as an example of this.
    
    
    // return collection.map(function(item){
    
    // return item[key] 

    // })

    return _.map(collection, function(item) {
      return item[key];
    });
  };

  // 각 항목에 대해 iterator(accumulator, item)를 반복적으로 호출하여, Reduces an array to a single value by repetitively calling
  // 하나의 값으로 줄입니다. accumulator는 누적값으로, 이전 iterator 호출의 반환값이어야 합니다.
  //
  // reduce에 대한 세번째 argument로 초기값을 전달 할 수 있습니다.
  // 만일 초기값이 전달되지 않으면, 첫번재 element가 accumulator로 사용되며, iterator에 전달되지 않습니다.
  // 즉, 초기값이 전달되지 않은 경우, iterator는 두번째 element로부터 시작합니다.
  //
  // 예제:
  //   const numbers = [1,2,3];
  //   const sum = _.reduce(numbers, function(total, number){
  //     return total + number;
  //   }, 0); // 6이 리턴됩니다
  //
  //   const identity = _.reduce([5], function(total, number){
  //     return total + number * number;
  //   }); // 5가 리턴됩니다, 전달한 iterator와 관계없이, 첫번째 element가 즉시 사용됩니다.
  
  _.reduce = function(collection, iterator, accumulator) {
     
     // 1. 내가 생각 방법
      let i=0;
      if (accumulator === undefined) {
        accumulator = collection[0];
        i++;
      }
      for(i; i<collection.length; i++) {
        accumulator = iterator(accumulator, collection[i]);
      }
      return accumulator;
    }
  // accumulator가 undefined면 : accumulator에게 첫 번째 collection값을 넣고,
  // 그 후 i++를 통해 collection[0]이 아닌 collection[1]부터 iterator가 돌아감
  // 
  
  
  // 2. 지훈씨 생각한 방법
  // for(let i=0; i<collection.length; i++) {
  //     if (accumulator === undefined) {
  //         accumulator = collection[0];
  //     } else {
  //         accumulator = iterator(accumulator, collection[i]);
  //     }
  // }
  // accumulator가 undefined면 : accumulator에게 첫 번째 collection값을 넣고,
  // if문에 걸리지 않은 iterator(accumulator, collection[0])은 pass함
  // 그 후 정상적으로 collection[1]부터 iterator가 돌아감
  // 마지막
  // return accumulator;
// }

  // 배열 또는 객체가 주어진 값을 포함하는지 체크합니다. (`===` 연산자를 사용해서 판단합니다.)
  _.contains = function(collection, target) {
 

    for (let i in collection ) {
      if (collection[i] === target ){
        return true
        } 
      }
      return false;
  }

    // 다른 깔끔한 방법
    // each 방법을 써서..

    // if (Array.isArray(collection)) {
    //   for (let i = 0; i < collection.length; i ++  ) {
    //     if (collection[i] === target) {  
    //       return true;
    //     } else {
    //       return false;
    //     }
    //   }
    // } else {
    //   for (let prop in collection) {
    //     if (collection[prop] === target) { 
    //       return true;
    //     } else {  
    //       return false;
    //     }
    //   }
    // } 
      



  // 모든 element가 iterator에 의해 truthy한지 체크합니다.
  _.every = function(collection, iterator) {
  
  // function every(collection,iterator)
  // collection.every(terator(value, key, collection)) ???
  
    if(iterator === undefined) { // 이것을 왜하는지 ?
      for(let i = 0 ; i < collection.length ; i++) {
        if(Boolean(collection[i]) === false) {
          return false;
        }  
      }
    } else if (iterator) { // 이것은 왜? 
      for (let j = 0 ; j < collection.length ; j++) {
        if (Boolean(iterator(collection[j])) === false) {
          return false;
        }
      }
    } return true;
  };

        // ??


//   if(collection.length !== 0){
//     if(iterator !== undefined){
//       arr = _.map(collection, function(ele){
//         return Boolean(iterator(ele));
//       });
//       arr = _.filter(arr, function(ele){
//         return ele === false;
//       });
//       return !(_.contains(arr, false));
//     } else {
//       arr = _.filter(collection, function(ele){
//         return ele === false;
//       });
//       return !(_.contains(arr, false));
//     }
//   } else {
//     return true;
//   }
// };



  // element가 하나라도 iterator에 의해 truthy한지 체크합니다.
  // iterator가 없다면, element 그 자체가 truthy한지 체크하세요.
  _.some = function(collection, iterator) {

    if(iterator === undefined) { // 이것을 왜하는지 ?
      for(let i = 0 ; i < collection.length ; i++) {
        if(Boolean(collection[i]) === true) {
          return true;
        }  
      }
    } else if (iterator) { // 이것은 왜? 
      for (let j = 0 ; j < collection.length ; j++) {
        if (Boolean(iterator(collection[j])) === true) {
          return true;
        }
      }
    } return false;
  };


  /**
  * OBJECTS
  * =======
  *
  * 이 섹션에서는, 객체를 서로 합쳐주는 몇개의 도우미 함수를 만들겁니다.
  */

  // 주어진 객체를 전달된 모든 속성으로 확장합니다.
  //
  // 예제:
  //   var obj1 = {key1: "something"};
  //   _.extend(obj1, {
  //     key2: "something new",
  //     key3: "something else new"
  //   }, {
  //     bla: "even more stuff"
  //   }); // obj1은 이제 다음 키를 포함합니다. key1, key2, key3, bla
  _.extend = function(obj, ...objs) {
  
    //객체를 합쳐주는 함수를 만들어보자
  
    for (let i = 0; i < objs.length; i ++ ) {
      for (let prop in objs[i] ) {
        obj[prop] = objs[i][prop];
      }
    }
    return obj;
  }
  

  //   for(let i = 0; i < arguments.length; i++) {
  //     for(let key in arguments[i]) {
  //     obj[key] = arguments[i][key]
  //     }
  //   } return obj;
  // };

  // extend와 비슷하지만, 이번엔 이미 존재하는 key에 대해 값을 덮어쓰기 하지 않습니다.
  _.defaults = function(obj,...objs) {
    
    for (let i = 0; i < objs.length; i ++ ) {
      for (let prop in objs[i]){
        // 만약 기존에있는 obj 의 키값이 새로 더해진 obj 에 없다면 
        if (!(prop in obj)) { 
          // 기존에 있는 obj 의 push 해준다. 
          obj[prop] = objs[i][prop];
        }
      }
    }
    return obj;
  }

  /**
  * FUNCTIONS
  * =========
  *
  * 이번엔 함수 데코레이터(decorator)를 사용합니다. 함수 데코레이터는 쉽게 말해, 어떤 함수를 받아들이고
  * 다소 다르게 작동하는 새로운 버전의 함수를 리턴하는 함수를 의미합니다.
  */

  // 최대 한번만 호출할 수 있는 함수를 리턴합니다. 이후의 호출은 이전에 한번 리턴된 값만을 리턴해야 합니다.
  
  

  // 질문 
  _.once = function(func) {
 
    // ... agrgs 사용한 함수 

    var alreadyCalled = false;
    let result;
    return function(...args) {
      if (!alreadyCalled) {
        alreadyCalled = true;
        result = func(...args);
      }
      return result;
    };
  };


  // this 와 arguments 와 apply 를 사용한 함수 

  //   let alreadyCalled = false;

  //   let result;

  
  //   return function() {
  //     if(alreadyCalled) {
  //       return result 
  //   } else {
  //       alreadyCalled = true 
  //       return result = func.apply(this, arguments);
  //     }
  //   }
  // };







  // 주어진 시간 (밀리초) 동안 함수를 지연한 다음 제공된 argument로 함수를 호출합니다.
  //
  // 원래 함수에 대한 argument는 wait parameter 뒤에 전달됩니다.
  // 예를 들어, 다음을 호출할 경우
  // _.delay(someFunction, 500, 'a', 'b');
  // someFunction('a', 'b') 은 500ms 이후에 호출됩니다.


  _.delay = function(func, wait, ...args) {

      setTimeout(function(){
        return func(...args);
      } ,wait);

  };


  /**
  * ADVANCED COLLECTION OPERATIONS
  * ==============================
  */

  // 다차원 배열을 가져와서, 1차원 배열로 변환합니다.
  // 새 배열에는 다차원 배열의 모든 요소가 포함되어야 합니다.
  //
  // Hint: Array.isArray 를 사용해 배열인지 아닌지를 체크하세요.
  _.flatten = function(nestedArray, result) {


     // 재귀를 이용한것 

     result = [];
     function flatarr(nestedArray) {
       for(let i = 0; i < nestedArray.length; i++) {
         if(!Array.isArray(nestedArray[i])) {
           result = result.concat(nestedArray[i])
         } else {
           flatarr(nestedArray[i]);
         }
       }
     } flatarr(nestedArray);
     return result;
   };
 










  // for 문을이용한 것 

  _.flatten = function(nestedArray) {
    //[1, [2], [3, [[[4]]]]]
    //oneflat([1, [2], [3, [[[4]]]]])
    // result = [1, 2, 3, [[[4]]]]
    // result = [1, 2, 3, 4]
    let oneflat = function(array) {
      let resultArr = []
      for (let i in array) {
        if (Array.isArray(array[i])) {
          resultArr = resultArr.concat(array[i]);
        } else {
          resultArr.push(array[i]);
        }
      }
      return resultArr;
    }
    let isinArr = function(array) {
      for (let i in array) {
        if (Array.isArray(array[i])) {
          return true;
        }
      }
      return false;
    }
    while(isinArr(nestedArray)) {
      nestedArray = oneflat(nestedArray);
    }
    return nestedArray;
  };





//   let arr = [];
//   let arr2 = [];
//   if(Array.isArray(nestedArray)) {
//     arr = nestedArray.join().split(',');
//   }
//   for(let i=0; i < arr.length; i++) {
//     arr2.push(Number(arr[i]));
//   }
//   return arr2;
// };







  // 배열 내용의 순서를 랜덤하게 변경합니다.
  //
  // TIP: 이 함수는 immutable해야 합니다.

  // 통과가 안됨 
  _.shuffle = function(array) {
    let newArr = [];
    let indexArr = [];
    let randomNum;
    let randomElement;
    for(let j = 0; j< array.length; j++) {
      indexArr.push(j);
    }
    let randomNumber = function(){
      return Math.floor(Math.random() * (array.length))
    }
    while(indexArr.length > 1) {
      randomNum = randomNumber();
      if (indexArr.includes(randomNum)) {
        randomElement = array[randomNum];
        newArr.push(randomElement);
        indexArr = _.filter(indexArr, function(el) {
          return el !== randomNum;
        });
      }
    }
    newArr.push(array[indexArr[0]]);
    return newArr;
 };
  /**
  * ADVANCED
  * =================
  *
  * Note: This is the end of the pre-course curriculum. Feel free to continue,
  * but nothing beyond here is required.
  */

  // Calls the method named by functionOrKey on each value in the list.
  // Note: You will need to learn a bit about .apply to complete this.
  _.invoke = function(collection, functionOrKey, args) {
  };

  // Sort the object's values by a criterion produced by an iterator.
  // If iterator is a string, sort objects by that property with the name
  // of that string. For example, _.sortBy(people, 'name') should sort
  // an array of people by their name.
  _.sortBy = function(collection, iterator) {
  };

  // Zip together two or more arrays with elements of the same index
  // going together.
  //
  // Example:
  // _.zip(['a','b','c','d'], [1,2,3]) returns [['a',1], ['b',2], ['c',3], ['d',undefined]]
  _.zip = function() {
  };

  // Takes an arbitrary number of arrays and produces an array that contains
  // every item shared between all the passed-in arrays.
  _.intersection = function() {
  };

  // Take the difference between one array and a number of other arrays.
  // Only the elements present in just the first array will remain.
  _.difference = function(array) {
  };

  // Memorize an expensive function's results by storing them. You may assume
  // that the function only takes primitives as arguments.
  // memoize could be renamed to oncePerUniqueArgumentList; memoize does the
  // same thing as once, but based on many sets of unique arguments.
  //
  // _.memoize should return a function that, when called, will check if it has
  // already computed the result for the given argument and return that value
  // instead if possible.
  _.memoize = function(func) {
  };

  // Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time.  See the Underbar readme for extra details
  // on this function.
  //
  // Note: This is difficult! It may take a while to implement.
  _.throttle = function(func, wait) {
  };
}());



Array 중복 제거하는 방법


var data = ['a' , 1, 2, 'a' , 'a', 3];

// 3가지 방법 from() + set , filter , reduce 

// 1: 'Set'
Array.from(new Set(data));

// 2: 'Filter' // arr 의 요소가 string 이라면 filter(ele,index,array) 사용한다. 
data.filter((ele, index,array) =>{
  return array.indexOf(ele) === index //array 3번째 파라미터를 이용하한다.  
})

//2 : filter // arr 요소가 숫자라면 
data.filter((ele, index,) =>{
  return data.indexOf(ele) === index //array 3번째 파라미터를 이용하한다.  
})




// 3: 'Reduce'
array.reduce((unique, item) =>
  unique.includes(item) ? unique : [...unique, item], []);
  

let names = ['Mike', 'John', 'Bob', 'Jane', 'Bob', 'John', 'Lee', 'Mason'] ;
 
let single = names.reduce(( a, b ) => {
	if( a.indexOf(b) < 0 ) a.push(b) ;
	return a ;
}, []) ; // <-- 초기값 빈 배열 세팅!
 
console.log( single ) ;
// [ 'Mike', 'John', 'Bob', 'Jane', 'Lee', 'Mason' ]


string 안에 알파벳 뽑기


str = "Hello6 9World 2, Nic8e D7ay!";

var sum = str.match(/\d/g).map(Number).reduce(function(a,c){
	return a + c;
})

str.replace(/[^a-z]/gi, ''); // "HelloWorldNiceDay"

string 안에 숫자뽑기

  • imutable

  • 숫자를 뽑는 역활

  • \d 는 모든 숫자를 각각 배열로 나눠서 출력한다.




let str = "123f456f78910";
str.match(/\d+/g);

// ["1", "2", "3", "4", "5", "6", "7", "8", "9", "1", "0"]

```js




* \d+ 숫자가 나란히 붙어있는 것으로 나뉜다. 

*  `imutable`

```js

let str = "123f456f78910";
str.match(/\d/g);

// ["123", "456", "789", "10"]



\d or \d+ 차이점


// 둘다 `imutable`  이다 

// 정규식 표현으로 둘다 숫자를 뽑는 역활을 한다. 

// \d 는 모든 숫자를 각각 배열로 나눠서 출력하낟.  

let str = "123f456f789 10";
str.match(/\d+/g);

// ["1", "2", "3", "4", "5", "6", "7", "8", "9", "1", "0"]




// \d+ 숫자가 나란히 붙어있는 것으로 나뉜다. 
let str = "123f456f789 10";
str.match(/\d/g);

// ["123", "456", "789", "10"]



Extract numbers from a string-Javascript

var string = "border-radius:10px 20px 30px 40px";
var numbers = string.match(/\d+/g).map(Number); 

console.log(numbers);

// [10, 20, 30, 40]



피보나치 수열 이란?

n 번째의 피보나치 수열에 숫자출력하는 fib(n) 함수만들기



// 0 1 1 2 3 5 8 13 21 34 ......
// 점화식표현은 ==> f(n) = f(n-1) + f(n-2)  

// 5번째 숫자는? = f(n-1) + f(n-2)  
// n = 5 
// 5-1 = 4  네번째 피보나치 수열에 있는 3은  숫자와 5-2 = 3 세번째 피보나치 에 있는 숫자 2 를 더한값이 된다. 



function fib(n) {    // n = 10 
    if (n <= 1) {    // 만약 n 이 0 과 1 이라면 
        return n;    // 그것을 그냥 바로 출력해라 
    } else {         // 만약 그게 아니라면 
        return fib(n-2) + fib(n-1);  //  피보나치 수열에 8번째수와  + 9번째 수의 합을 리턴한다.  그럼 8번째 있는 수는 21 이고 9번째 있는 수는 34 이기 때문에 더한 값은 55가 된다. 

    }
}

fib(10) // ==> 55


function fib(n) {
 
	if (n === 0 ) { // n 이 0 이면 0을 출력하고 그만  
	return 0;      
	}
	if (n === 1 ) { // n 이 1 이면 1을 출력하고 그만 
	return 1;
}


return fib(n-1) + fib(n-2) 
	
}




20번째 까지 피보나치 수열을 출력하는 fib(n) 함수 만들기



function fib(n) {
    if ( n <= 1 ) {
        return n;
    } else {
        return fib(n - 1) + fib(n - 2);
    }
}

let  tmp = '';

for(let i = 0; i < 20; i++){ // 20번째 까지 
    tmp += fib(i) + " " 
}


함수사용해서 피보나치 수열 만들기






function fibonacci(num){
    var a = 1 
	  var b = 0
	  var temp;
	  
	  for(var i = num; i >= 1; i--){
            temp = a;
            a = a + b;
            b = temp;
            
			if(i === 1) {
			console.log(b);
            }	else {
			console.log(b);
      			
   		 }
        }
}

for 문을 사용해서 피보나치 수열 만들기




var num = 15;  // 몇번째까지 
var a = 1, b = 0, temp;

document.write(b + ", ");

for(var i = num; i >= 1; i--){
temp = a;
a = a + b;
b = temp;
if(i == 1) {
document.write(b);
} else {
document.write(b + ", ");
}
}

# forEach, for of, for in 의 차이

basic for문과 for in은 반복변수에 index를 리턴하지만

forEach 와 for of 는 해당 값을 리턴하기 때문이죠.


const array = ['가','나','다','라'];

// for
for(let i=0; i<array.length; i++){
  console.log(array[i]);
}

// 가 나 다 라 


 
//forEach
array.forEach(function(j){
  console.log(array[j]);
});
 
// console.log(array[j]) 
// undefined
 
// console.log(j) 
// 가 나 다 라
 
 
 
 
// for of 
for (let k of array){
  console.log(array[k]);
}
 
// console.log(array[k]) 
// undefined
 
// console.log(k) 
// 가 나 다 라
 
 
 
 
 // for in
for (let z in array){
  console.log(array[z]);
}

// 가 나 다 라



Falsy 와 Fruthy 구별


undefined, false, null, 0, NaN,   false  취급(falsy)
(NaN : Not a Number)

/위에 적힌 데이터가 아닌 모든 데이터는 trye로 취급(truthy)

null 과 undefined 는 등록, 저장 여부이다.

null 은 값은 값이지만 값으로써 의미없는 특별한 값이 등록되어 있는 것이고, undefined 는 등록이 되어있지 않기 때문에 초기화도 정의되지도 않은 것입니다.

undefined 는 미리 선언된 전역변수(전역 객체의 프로퍼티)이며, null 은 선언,등록을 하는 키워드인 것입니다.

객체인 arguments 를 array 로 바꾸는 방법

  • call()은 상위 context를 변경하는 메서드이고

  • arguments는 함수의 매개변수에 접근할 수 있는 속성이다.

먼저 위의 행위를 말로 설명하자면 이 코드가 존재하는 함수의 매개변수로 넘어온 값들을 array로 변환하겠다는 것이다.

function func(a, b){} 에서 a와 b를 arguments[0]과 arguments[1]로 접근가능하다.

하지만 여기서 arguments는 array가 아니며 object임을 알아야 한다.(참고) 그러므로 array로 변환할 필요가 있을 경우

  • 바꾸는 코드
Array.prototype.slice.call(arguments) // 를 사용하는 것이다.

  • 설명

 코드는 보통 아래와 같이 apply와 함께 사용된다.

var args = Array.prototype.slice.call(arguments);

func.apply(this, args); 

apply는 call과 같이 상위 context를 변경해준다. 차이점은 매개변수를 넘겨주는 2번째 인자가 Array라는 점이다. Array에 담긴 순서에 맞게 호출된 함수(func) 매개변수에 적용된다.



Array.prototype.slice.call(arguments);

 코드는 결과만 보면 아래와 같다.

[arguments].slice();

call() 첫번째 인자에 arguments가 전달되므로 Array의 context는 arguments로 대체되기 때문이다.



추가로 ES6에서는 Array.from()으로 제공한다(참고)



결론

결국 이러한 행위는 문법적 꼼수라고   있다.

v8엔진에서 최적화 문제도 있다고 하니 다음 코드를 사용해보는 것도 좋다.

var args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));

# Rest파라미터와 Spread연산자 or 함수의 가독성을 높이는 방법

  • Rest 파라미터 (Rest Parameter)

Rest 파라미터는 Spread 연산자(...) 사용하여 함수의 파라미터를 작성한 형태를 말한다. , Rest 파라미터를 사용하면 함수의 파라미터로 오는 값들을 "배열" 전달받을  있다.

(Java에서 public static void func(String... strs){...} 이런식의 가변인자와 유사)

사용 방법은 파라미터 앞에 (...) 붙인다.


function foo(...rest) {
  console.log(Array.isArray(rest)); // true
  console.log(rest); // [ 1, 2, 3, 4, 5 ]
}
foo(1, 2, 3, 4, 5);


* function foo(param1, param2, ...rest){~~} 처럼 앞에 파라미터는 일반적인 파라미터로 받을  있고  뒤부터는 Rest 파라미터로 받을  있다.

- , Rest파라미터는 항상 제일 마지막 파라미터로 있어야 한다. 예를들어 function foo(...rest, param1, param2){~} 사용 불가능하다.

arguments VS rest 파라미터

ES5에서도 가변 인자 함수의 경우 arguments 객체를 통해 인자값을 확인할  있었다.


var foo = function () {
  console.log(arguments);
};
foo(1, 2); // { '0': 1, '1': 2 }


그렇다면 arguments와 rest파라미터의 차이점은 무엇일까?

답부터 말하면 arguments는 유사 배열 객체고 rest는 배열이다.

유사 배열 객체(array-like object) 간단하게 순회가능한(iterable) 특징이 있고 length 값을   있는 특징이 있는 것이다. , 배열처럼 사용할  있는 객체를 말한다.

무슨 말이냐면 arguments는 유사배열객체이기 때문에 Array 오브젝트의 메서드를 사용할  없다.

따라서 ES6에서는 arrow function에 arguments는 사용할  없을 뿐더러 Rest 파라미터를 사용하면  유연한 코드를 작성할  있는 것이기 때문에 Rest 파라미터 사용을 권장한다.


  • Spread 연산자 (Spread Operator)

Spread 연산자는 연산자의 대상 배열 또는 이터러블(iterable) "개별" 요소로 분리한다.


// 배열
console.log(...[1, 2, 3]); // -> 1, 2, 3
 
// 문자열
console.log(...'Helllo');  // H e l l l o
 
// Map과 Set
console.log(...new Map([['a', '1'], ['b', '2']]));  // [ 'a', '1' ] [ 'b', '2' ]
console.log(...new Set([1, 2, 3]));  // 1 2 3
Colored by Color Scripter


이터러블(iterable) Array, String, Map, Set, DOM구조다.

iterator를 생성해서 next() 순회할  있는 자료구조가 이터러블이라고 생각하면 된다.

* 함수의 파라미터로 사용하는 방법


// ES6
function foo(x, y, z) {
  console.log(x); // 1
  console.log(y); // 2
  console.log(z); // 3
}
const arr = [1, 2, 3];
foo(...arr);// Array를 받아서 각 매개변수로 전달되었다.


Rest와 헷갈리지 않기!

Rest는 함수 선언문의 파라미터에 Spread(...)연산자를 이용해서 받으면 가변인자를 받아 배열로 만들어서 사용하는 것이고, 함수 호출문의 파라미터에 Spread(...)연산자를 이용해서 호출하면 배열이 해당 매개변수로 각각 매핑되는 것은 다르다.

//Rest
function foo(param, ...rest) {
  console.log(param); // 1
  console.log(rest);  // [ 2, 3 ]
}
foo(1, 2, 3);
 
//Spread호출
function bar(x, y, z) {
  console.log(x); // 1
  console.log(y); // 2
  console.log(z); // 3
}
bar(...[1, 2, 3]);


- 또한 Rest에서는 선언에서 Spread연산자를 제일 뒤에만 써야하지만, Spread호출에서는 중간중간 사용해도 상관없다.

* 배열에서 사용하는 방법 (가독성UP)


//ES5
var arr = [1, 2, 3];
console.log(arr.concat([4, 5, 6])); // [ 1, 2, 3, 4, 5, 6 ]
 
// ES6
const arr = [1, 2, 3];
// ...arr은 [1, 2, 3]을 개별 요소로 분리한다
console.log([...arr, 4, 5, 6]); // [ 1, 2, 3, 4, 5, 6 ]


- concat() 대신 가독성이  좋아졌다.


// ES5
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
 
// apply 메소드의 2번째 인자는 배열. 이것은 개별 인자로 push 메소드에 전달된다.
//Array.prototype.push.apply(arr1, arr2);
//arr1.push(arr2); => [1,2,3,[4,5,6]]
console.log(arr1); // [ 1, 2, 3, 4, 5, 6 ]
 
// ES6
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
 
// ...arr2는 [4, 5, 6]을 개별 요소로 분리한다
arr1.push(...arr2); // == arr1.push(4, 5, 6);
 
console.log(arr1); // [ 1, 2, 3, 4, 5, 6 ]


- push를 개별 요소로 전달할  있으니 훨씬 간결하고 가독성 또한 좋아졌다.

* 객체에서 사용하기

const o1 = { x: 1, y: 2 };
const o2 = { ...o1, z: 3 };
console.log(o2); // { x: 1, y: 2, z: 3 }
 
const target = { x: 1, y: 2 };
const source = { z: 3 };
// Object.assign를 사용하여도 동일한 작업을 할 수 있다.
// Object.assign은 타깃 객체를 반환한다
console.log(Object.assign(target, source)); // { x: 1, y: 2, z: 3 }