반응형

실제 기기 없이 에뮬레이터에서 테스트 하기 위한 방법!!

 

1. 안드로이드 에뮬레이트 생성

안드로이드 스튜디오에서 AVD Manager 버튼을 클릭.

 

좌측 하단의 Create Virtual Device... 버튼을 클릭

 

Category 에서 Phone 선택 후 Pixel 2 를 선택. Next 버튼 클릭.

 

OS는 API 33 을 선택!! Download 하면 된다. Next 버튼 클릭.

 

에뮬레이터 이름을 설정하고.. 좌측 하단의 Show Advanced Settings 버튼 클릭.

 

Internal Storage 를 넉넉하게 8GB 로 설정. Finish 클릭하여 완료한다.

 

에뮬레이터가 추가 된 것을 확인 할 수 있다.(기존에 API 30 은 삭제했다)

 

2. iOS 심뮬레이터는 Mac OS 환경에서 가능하므로... 패스... --;;

 

 

반응형
반응형

이제 직접 코딩하면서 배워보자!!

그동안 손이 근질근질.. 눈꺼풀이 천근만근이었을 것이다!!

 

1. 안드로이드 스튜디오에서 플러터 프로젝트 생성(GUI)

File > New > New Flutter Project...

 

Flutter Application 선택

 

Application 설정.

 - 소스 위치 : [플러터 프로젝트 디렉토리]\[플러터 프로젝트 명]

 - 플러터 SDK 설치 Path 설정

 

마지막으로 패키지 명을 입력 후 Finish

 

2. CLI 로 프로젝트 생성

$ flutter create hello_world2

....

All done!
You can find general documentation for Flutter at: https://docs.flutter.dev/
Detailed API documentation is available at: https://api.flutter.dev/
If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev

In order to run your application, type:

  $ cd hello_world2
  $ flutter run

Your application code is in hello_world2\lib\main.dart.

 

안드로이드 스튜디오에서 가져오기

 - CLI 로 생성한 hello_world2 디렉토리 Open

 

안드로이드 스튜디오에서 프로젝트 확인

 - hello_world\lib\main.dart 파일이 메인

 

반응형
반응형

Flutter는 고성능, 고품질의 iOS, Android, 웹(tech preview) 앱을 단일 코드 베이스로 개발할 수 있는 모바일 앱 SDK입니다.

 

스크롤 동작, 글씨, 아이콘과 같이 플랫폼 별로 달라지는 부분들을 아울러서 서로 다른 플랫폼에서도 자연스럽게 동작하는 고성능의 앱을 개발할 수 있게 하는 것이 Flutter의 목표입니다.

 

Flutter의 장점
● 높은 생산성
    ○ 단일 코드베이스로 iOS와 Android 개발할 수 있습니다.
    ○ 모던하고 표현적인 언어 그리고 선언적 접근법을 통해 단일 OS에서 더 적은 코드로 더 많은 것을 할 수 있습니다.
     쉽게 프로토타입을 제작하고 반복할 수 있습니다.
        √ 앱 실행 중에 코드를 바꾸고 리로드하여 개발을 할 수 있습니다. ( hot reload)
        √ 앱이 중단된 지점에서 문제를 수정하고 디버깅을 이어나갈 수 있습니다.

 아름답고, 고도로 커스터마이징된 UX를 만들 수 있습니다.
     Flutter의 자체 프레임워크를 사용하여 머티리얼 디자인과 쿠퍼티노 (iOS) 스타일의 풍부한 위젯들을 만들 수 있습니다.
     OEM 위젯의 제한없이 맞춤형의 아름다운 브랜드 주도 디자인을 실현할 수 있습니다.

 

핵심 원리

Flutter는 현대적인 react-style 프레임워크, 2D 렌더링 엔진, 바로 이용 가능한 위젯들, 그리고 개발 툴들을 포함합니다.

이러한 구성 요소들을 통해 앱을 디자인, 개발, 테스트 그리고 디버깅할 수 있습니다. 모든 것은 몇가지 핵심 원리들을 중심으로 구성됩니다.

 

모든 것은 위젯입니다

위젯은 Flutter 앱 UI의 기본 단위입니다. 모든 위젯은 UI의 불변 선언입니다. 

뷰, 뷰 컨트롤러, 레이아웃 그리고 기타 다른 속성들을 분리하는 다른 프레임워크들과 다르게, Flutter는 일관적이고 통일된 오브젝트 모델을 갖고 있는데, 그것이 바로 위젯입니다.

 

 

위젯은 다음의 것들을 정의할 수 있습니다:

● 구조적인 요소 (예: 버튼이나 메뉴)

● 스타일적인 요소 (예: 폰트나 색상)

● 레이아웃 요소 (예: 패딩)

● 기타 등등…

위젯은 구성을 기반으로 계층 구조를 형성합니다. 

각 위젯은 내부에 중첩되고 부모의 속성들을 상속받습니다.

별도 “application” 오브젝트가 없는 대신 최상위 위젯이 그 역할을 하게 됩니다.

 

프레임워크에게 위젯을 계층 구조 상 다른 위젯으로 교체하게 함으로써, 사용자 상호작용과 같은 이벤트를 구현할 수 있습니다. 프레임워크는 새로운 위젯과 기존 위젯을 비교하고 효을적으로 UI를 업데이트하게 됩니다.

 

구성 > 상속

위젯은 종종 강력한 효과를 내기 위해 단일 목적의 여러 작은 위젯들로 구성됩니다. 

예를 들어, 일반적으로 사용되는 Container 위젯은 painting, positioning, sizing과 같은 레이아웃 관련 위젯들로 구성됩니다. 

좀더 구체적으로 Container는 LimitedBox, ConstrainedBox, Align, Padding, DecoratedBox, Transform 위젯들로 구성됩니다. 

커스터마이징을 위해 Container의 서브 클래스를 만들기 보다는 앞서 언급한 위젯들 혹은 그외 다른 간단한 위젯들을 참신한 방법으로 조합할 수 있습니다.

 

가능한 조합의 수를 최대화하기 위해 클래스 계층 구조는 얕고 넓습니다.

다른 위젯들과 함께 구성하는 방식으로 위젯의 레이아웃을 조작할 수 있습니다.

예를 들어, 위젯을 가운데로 위치시키려면 그 위젯을 Center 위젯으로 감싸면 됩니다.

패딩, 정렬, 행, 열, 그리드와 같은 여러 레이아웃 위젯들이 있는데, 이러한 레이아웃 위젯들은 그 자체로 시각적 표현을 갖고 있지는 않습니다.

이들의 유일한 목적은 다른 위젯의 레이아웃을 제어하는 것이기 때문입니다. 만약 어떤 위젯이 어째서 이렇게 렌더링된건지 궁금하다면, 인근에 위치한 다른 위젯들을 살펴보면 알 수 있습니다.

 

Flutter 프레임워크는 각각의 층이 이전 층에 의해 빌드되는 일련의 층으로 구성되어 있습니다.

 

프레임워크의 상위 레이어로 갈수록 하위 레이어보다 더 빈번히 사용됩니다. 

Flutter의 계층화된 프레임워크를 구성하는 전체 라이브러리는 API 문서에서 확인할 수 있습니다.

이러한 설계의 목표는 개발자로 하여금 더 적은 코드로 더 많은 일을 할 수 있게 하는 것입니다.

예를 들어, 머티리얼 계층은 위젯 계층의 기본적인 위젯들을 조합하여 만들어지고, 위젯 계층은 렌더링 계층의 하위 레벨 오브젝트들의 조합으로 만들어집니다.

계층들은 앱을 만드는데 많은 옵션을 제공합니다. 

프레임워크의 풍부한 표현력을 활용할 수 있는 커스터마이즈한 접근법을 선택하거나 위젯 계층의 블럭들을 사용하세요, 혹은 이것들을 조화롭게 잘 조합하여 사용하세요. 

Flutter가 제공하는 자체 위젯들을 사용하거나, Flutter 팀에서 프레임워크 개발할 때 사용한 것과 동일한 도구와 기술들을 갖고 직접 커스텀 위젯도 만들 수 있습니다.

모든 것은 공개되어 있습니다. 프레임워크의 하위 계층을 뜯어보지 않고도 상위 레벨의 위젯 컨셉만으로도 생산성을 높일 수 있습니다.

 

반응형
반응형

다트 언어는 객체지향 프로그래밍을 지원한다.

 

클래스

// class 정의.
class Person {

	// class 종속 변수
	String name = '이름';
    
    // class 종속 함수 = 메소드
    // 내부 속성을 사용할 때 this 키워드 사용.
    void sayName() {
    	print('My name is ${this.name}');
    }
    
}

 

인스턴스 생성

void main() {
	// 인스턴스 생성
	Person person = Person();
    
    // 메소드 실행.
    person.sayName();
}

 

생성자

class Person {
	// 생성자에서 입력 받는 변수들은 일반적으로 final 키워드 사용.
	final String name;
    
    // 생성자 선언. class 와 같은 이름.
    // 매개변수 지정
    Person(String name) : this.name = name;
    
    // this 를 사용할 경우.
    // 해당되는 변수에 자동을 매개변수가 저장.
    Person(this.name);
    
    void sayName() {
    	print('My name is ${this.name}');
    }
    
}

void main() {
	Persion person = Person('홍길동');
}

 

네임드 생성자

class Person {
	final String name;
    final int age;
    
    // 1개 이상의 변수를 저장할때는 , 기호로 연결.
    Person(String name, int age)
    	: this.name = name,
          this.age = age;
    
    // 네임드 생성자
    Person.fromMap(Map<String, dynamic> map)
    	: this.name = map['name'],
          this.age = map['age'];
    
    void sayName() {
    	print('My name is ${this.name}');
    }
    
}

void main() {
	Persion person = Person('홍길동', 20);
    Persion hong = Person.fromMap({
    	'name' : '홍길동',
        'age' : 20,
    });
}

 

private 변수

class Person {
	// '_' 로 시작하면 private 변수 선언.
	String _name;
    
    Person(this._name);
    
    void sayName() {
    	print('My name is ${this._name}');
    }
    
}

void main() {
	Persion person = Person('홍길동');
    print(person._name); // 같은 파일에서는 에러가 발생하지 않지만 다른 파일에서 사용시 에러 발생.
}

 

Getter / Setter

class Person {
	String _name = 'hong';
    
    // get 키워드를 사용하여 getter 명시
    // 매개변수를 받지 않음.
    String get name {
    	return this._name;
    }
    
    // set 키워드를 사용하여 setter 명시
    // 매개변수로 하나의 변수를 받음.
    set name(String name) {
    	this._name = name;
    }
    
}

void main() {
	Persion person = Person();
    person.name = '홍길동'; // setter
    print(person.name); // getter
}

 

상속

class Person {
	final String name;
    
    Person(this.name);
    
    void sayName() {
    	print('My name is ${name}.');
    }
}

// 상속
class Man extends Person {
	// 상속 받은 생성자
    // super 는 부모 클래스를 의미한다.
	Man(String name) : super(name);
    
    void sayMan() {
    	print('I am a man');
    }
}

void main() {
	Man man = Man('홍길동');
	print(man.sayName()); // 부모한테 물려받은 메소드
    print(man.sayMan()); // 자식이 추가한 메소드
}

 

오버라이드

class Person {
	final String name;
    
    Person(this.name);
    
    void sayName() {
    	print('My name is ${name}.');
    }
}

class Girl extends Person {
    // super 키워드를 직접 사용할 수 있음.
	Girl(super.name);
    
    @override
    void sayName() {
    	print('My name is ${name} and I am a girl');
    }
}

void main() {
	Girl girl = Girl('영희');
	print(girl.sayName()); // override 된 메소드
}

 

인터페이스

// implements 키워드를 사용하면 클래스를 인터페이스로 사용할 수 있다.
class Girl implements Person {
    final String name;
    
	Girl(super.name);
    
    // 인터페이스로 사용할 때는 모든 메소드를 재정의 해야한다.
    void sayName() {
    	print('My name is ${name}');
    }
}

void main() {
	Girl girl = Girl('영희');
	print(girl.sayName());
}

 

믹스인???

 - 이건 잘 모르겠다... --;;;

 

추상 클래스

 - 인스턴스화 할 필요가 없을 경우에 사용

// abstract 키워드를 사용하여 추상 클래스 정의.
abstract class Person {
	final String name;
    
    // 생성자 선언
    Person(this.name);
    
    // 추상 메소드 선언.
    void sayName();
}

// implements 키워드를 사용하여 추상 클래스를 구현.
// 생성자를 비롯하여 모든 메소드를 정의해야 한다.
class Girl implements Person {
	final String name;

    // super 키워드를 직접 사용할 수 있음.
	Girl(this.name);
    
    void sayName() {
    	print('My name is ${name} and I am a girl');
    }
}

void main() {
	Girl girl = Girl('영희');
    print(girl.sayName());
}

 

제너릭

// 제너릭
// 특정 변수의 타입을 제한하고 싶지 않을 때 사용.
// 인스턴스화 할 때 입력받을 타입을 T 로 지정.
class Generate<T> {
	// 데이터 타입을 인스턴스화 할 때 지정한 타입으로 사용.
	final T data;
    
    Generate({
    	required this.data,
    });
}

void main() {
	// 제너릭에 입력된 값을 통해 data 변수의 타입이 자동으로 유추.
	final gen = Generate<List<int>> (data : [1, 2, 3]);
    print(gen.data.reduce((v,e) => v + e); // 6
}

 

static

class Count {
	// static 은 클래스 자체에 귀속
	static int i = 0;
    
    // 생성자가 호출될때 마다 i 증가.
    Count() {
    	i++;
        print(i);
    }
}

void main() {
	Count c1 = Count(); // 1
    Count c2 = Count(); // 2
    Count c3 = Count(); // 3
}

 

Cascade

class Person {
	final String name;
    final int age;
    
    Person(this.name, this.age);
    
    void sayName() {
    	print('My name is ${this.name}');
    }
    
    void sayAge() {
    	print('My age is ${this.age}');
    }
}

void main() {
	// cascade 연산자 ..
    // 인스턴스의 속성이나 메소드를 연속해서 사용하는 것.
	Person person = Person('홍길동', 20)
    	..sayName()
        ..sayAge();
}

 

오늘은 다트의 객체지향 프로그래밍에 대해서 공부했다!!

 

반응형
반응형

플러터는 다트(Dart) 언어를 사용합니다.

다트를 알아야 플러터로 앱 개발이 가능하므로 다트를 공부해야합니다.

다트는 구글에서 개발한 프로그래밍 언어입니다.

다트는 모바일이나 데스크탑 기기를 타겟으로 하는 네이티브 플랫폼과 웹을 타켓으로 하는 웹 플랫폼으로 컴파일 할 수 있습니다.

다트 공부하기

1. 다트패드에서 공부하기

다트패드 홈페이지에서 코드 작성 및 실행 가능합니다.
 

DartPad

 

dartpad.dev

코드 작성 후 Run 버튼을 클릭하여 실행 결과를 확인 할 수 있다.

 

2. 안드로이드 스튜디오에서 공부하기

File -> New -> New Flutter Project ... 메뉴를 클릭하여 플러터 프로젝트를 생성한다.

lib/main.dart 파일에 코드를 작성 후 안드로이드 스튜디오 하단의 터미널 탭에서 dart lib/main.dart 명령어를 실행한다.

 

 

기초 문법

메인 함수

void main() {
	// 한줄 주석
    
    /* 시작기호, 끝 기호 */
    /* 여러 줄 주석
    * 
    *
    * */
    
    /// 슬래시 세 개를 사용하면 문서 주석을 작성할 수 있습니다.
    
}

 

변수 선언

// 변수 타입
String(문자열), int(정수형), double(실수형), bool(불리언 true/false)
String s = '';
int i = 1;
double d = 1.0;
bool b = true;

// 자동으로 타입을 추론. 한번 추론된 타입은 고정됨.
var name = '이름';

// 추후에 타입이 바뀌면 에러
name = 1; // 에러

// dynamic 키워드를 사용하면 변수 타입을 고정하지 않고 사용 가능.
dynamic d_name = '다이내믹';
d_name = 1;

// final, const 는 처음 선언 후 값 변경이 불가하다.
final String f_str = 'final string';
f_str = 'new string'; // 에러 발생

const String c_str = 'const string';
c_str = 'new const'; // 에러 발생

// final 은 런타임, const 는 빌드타임 상수이다.
// DateTime.now() 는 실행되는 순간(런타임 시) 값이 정해진다.
final DateTime f_now = DateTime.now();
const DateTime c_now = DateTime.now(); // 에러 발생

// 컬렉션
// List
List<String> list = ['s1', 's2', 's3'];
print(list[3]); // s3
list.add('s4');
final list_where = list.where((str) => str == 's1' || str == 's4'); // Iterable (s1, s4)
print(list_where.toList()); // [s1, s4]
final list_map = list.map((str) => 'new $str'); // Iterable (new s1, new s2, new s3, new s4);
final list_reduce = list.reduce((v, e) => v + ', ' + e); // (반환 타입이 String) s1, s2, s3, s4
final list_fold = list.fold(0, (v, e) => v + e.length); // (반환 타입 아무거나 가능) 8

// Map
Map<String, String> map = {
	'a' : 'a1',
    'b' : 'b2',
    'c' : 'c3',
};
print(map['b']); // b2
print(map.keys); // Iterable (a, b, c)
print(map.values); // Iterable (a1, b2, c3)

// Set
Set set = {'s1', 's2', 's3'};
set.contain('s2'); // true
set.toList(); // Set to List
Set.from(list); // Set from List

// enum
enum Status {
	ready,
    play,
    done,
}

Status status = Status.ready;
print(status); // Status.ready

 

연산자

// 사칙연산
+
-
*
/ // 몫
% // 나머지
++
--
+=
-=
*=
/=


// null 관련 연산자
// nallable
double? number1 = 1;

// not null
double number2 = null; // 에러 발생

// null 로 초기화
double? number;

// null 이면 할당.
number ??= 3; // 3

// not null 이면 할당하지 않음.
number ??= 4; // 3


// 값 비교
>
<
>=
<=
==
!=


// 타입 비교
print(number is int); // false
print(number is double); // true
print(number is! int); // true
print(number is! double); // false


// 논리 연산자
&&
||

 

제어문

if
else if
else

switch() {
	case 1 :
    	print();
    	break;
    default:
    	print();
}

for(int i=0; i < 10; i++) {
	print(i);
}

List<int> list = [1,2,3];
for(int n in list) {
	print(n);
}

while() {
}

do {
} while()

 

함수와 typedef

void main() {
	// 고정된 매개변수(포지셔널 파라미터)
      print(addTwoNumbers1(2, 3));

      // 이름이 있는 매개변수(네임드 파라미터)
      print(addTwoNumbers2(a:2, b:3));

      // 고정된 매개변수 기본값 지정
      print(addTwoNumbers3(2));
      print(addTwoNumbers3(2, 1));

      // 이름이 있는 매개변수 기본값 지정
      print(addTwoNumbers4(a:2));
      print(addTwoNumbers4(a:2, b:1));


      // typedef 는 일반적인 변수의 type 처럼 사용.
      Operation oper = add;
      oper(1, 2);

      oper = subtract;
      subtract(5, 2);

      calculate(3, 4, add);
}

// 함수의 시그니처 정의.
typedef Operation = void Function(int x, int y);

void add(int x, int y) {
  print('Add Result = ${x + y}');
}

void subtract(int x, int y) {
  print('Subtract Result = ${x - y}');
}

// dart 에서 함수는 일급 객체(일급 시민)이므로 함수를 값처럼 사용 가능.
// typedef 으로 선언한 함수를 매개변수로 사용 가능.
void calculate(int x, int y, Operation oper) {
  oper(x, y);
}

int addTwoNumbers1(int a, int b) {
  return a + b;
}

int addTwoNumbers2({required int a, required int b}) {
  return a + b;
}

int addTwoNumbers3(int a, [int b=3]) {
  return a + b;
}

int addTwoNumbers4({required int a, int b=3}) {
  return a + b;
}

 

기본 문법은 이정도로 정리하겠다.^^

반응형
반응형

본격적인 개발을 위한 도구인 안드로이드 스튜디오를 설치해보자.

공식 사이트에서 다운로드 한다.
 

Android 개발자  |  Android Developers

Android 앱 개발자를 위한 공식 사이트입니다. Android SDK 도구 및 API 문서를 제공합니다.

developer.android.com

 

그 다음 Flutter 플러그인을 설치한다.

File -> Settings 메뉴에서 Plugins 에서 flutter 검색 후 install 한다.

 

이제 개발을 위한 준비를 마쳤다.

본격적으로~~ 개발을 해보자!!

 

반응형
반응형

안드로이드와 iOS 앱을 만들수 있는 플러터를 알아보기로 했다.

먼저, 설치 부터 시작!

공식 사이트에서 Get Started 클릭.
※ 한글 사이트도 제공하고 있으니 참고하면 좋을 것 같다.
자신의 OS에 맞게 다운로드 한다.(Windows)


SDK 를 다운받아 원하는 위치에 압축을 풀면 된다.

현재 버전은 3.7.10

 

플러터 명령어를 실행하기 위해 환경 변수 설정!

윈도우 -> 설정
윈도우 - 설정



설정 창에서 "시스템 환경 변수" 검색



시스템 속성 창에서 "환경 변수" 클릭



시스템 환경 변수 추가
환경 변수 창에서 "시스템 변수"의 Path 편집 클릭
환경 변수 편집 창에서 "새로 만들기" 클릭하여 "플러터 SDK 압축 푼 디렉토리\bin" 추가 


cmd 창에서 설치 버전 확인

 

반응형
반응형




Spring Properties 파일 로딩 우선 순위
 - 1이 가장 높음


# ############################ #
# 파일 위치(디렉토리) 우선 순위 설정.
# ############################ #


# default
1. file:./config/
2. file:./
3. classpath:/config/
4. classpath:/


# spring.config.additional-location
# - 기본 spring.config.location 에 추가.
ex) spring.config.additional-location=classpath:/custom-config/,file:./custom-config/
1. file:./custom-config/
2. classpath:custom-config/
3. file:./config/
4. file:./
5. classpath:/config/
6. classpath:/


# spring.config.location(기본값 : classpath:/,classpath:/config/,file:./,file:./config/)
# - 나중에 기술된 위치가 우선 순위가 높음.
# - 디렉토리 / 파일명 모두 명시 가능
# - 디렉토리를 명시 했을 경우 profile 설정 사용 가능.
ex) spring.config.location=classpath:/custom-config/,file:./custom-config/
1. file:./custom-config/
2. classpath:custom-config/



# ############################ #
# 파일명(profiile) 우선 순위 설정.
# ############################ #


# spring.profiles.active 설정.
# - 나중에 기술된 profile(dev) 이 우선순위가 높음.
ex) spring.profiles.active=common,dev
1. application-dev.properties
2. application-common.properties
3. application.properties


# spring.profiles.include 설정.
# - include 된 profile 이 우선순위가 높음.
ex) application.properties 파일 내용(spring.profiles.include=common)
1. application-common.properties
2. application.properties

 

# spring.profiles.active & spring.profiles.include 설정.
# - spring.profiles.active 의 profile 이 우선순위가 높음.
ex) spring.profiles.active=dev

ex) spring.profiles.include=common
1. application-dev.properties
2. application-common.properties
3. application.properties

 

 

# 환경 변수 -Dspring.profiles.active=prd

# vs

# 프로퍼티 spring.profiles.active=dev(application.properties 파일 내용)

# 환경변수의 profile 이 적용된다.

1. application-prd.properties
2. application.properties

 

 

반응형

'프로그래밍 > Spring' 카테고리의 다른 글

Spring logback 설정 우선 순위  (0) 2023.06.09
반응형

java encoding 순서

System.out.println("file.encoding=" + System.getProperty("file.encoding"));
System.out.println("Charset.defaultCharset=" + Charset.defaultCharset());
System.out.println("InputStreamReader.getEncoding=" + new InputStreamReader(new FileInputStream("./PrintCharSets.java")).getEncoding());

 

1. jvm 옵션(OS 환경변수보다 최우선시 적용)

 - java -Dfile.encoding=euckr

2. env LC_ALL

- LC_ALL 이 설정되어 있으면 LC_CTYPE 값도 LC_ALL 값으로 덮어써진다.

3. env LC_CTYPE

- LC_ALL 이 설정 안되어 있으면 개별로 설정된 LC_CTYPE 적용.

4. env LANG

- LC_ALL 과 LC_CTYPE 이 설정되어 있지 않다면 LC_ALL 을 제외한 나머지 LC_* 값은 LANG 값으로 덮어써진다.

- 따라서, LC_CTYPE 은 LANG 값과 같아진다.

 

결국 linux 에서는 jvm 옵션을 설정하지 않으면 locale 명령어의 결과 중 LC_CTYPE 값이 적용된다고 보면 된다.

 

반응형

'프로그래밍 > Java' 카테고리의 다른 글

Java Stream 설명  (0) 2023.05.26
Stream reduce 간단 설명  (0) 2023.05.20
[JAVA] java.lang.UnsatisfiedLinkError: no net in java.library.path  (1) 2021.06.25
Too many open files  (2) 2021.06.14
환경변수 값 읽어오기.  (0) 2021.04.05
반응형

undefined는 원시값으로, 선언한 후 값을 할당하지 않은 변수 혹은 값이 주어지지 않은 인수에 자동으로 할당됩니다.

var a;

if(typeof a === 'undefined') {
        console.log('a is typeof undefined');
}

if (a === undefined) {
        console.log('a is undefined');
}

 

그렇다면 선언하지 않은 변수는 어떻게 되나???

if (b === undefined) {
        console.log('b is undefined');
}

===> ReferenceError 발생.

 

if (typeof b === 'undefined') {
        console.log('b is typeof undefined');
}

===> 오류 없이 로그 출력.

 

 

결론... typeof 를 사용하자??!!!

typeof를 사용하는 이유 중 하나는 선언하지 않은 변수를 사용해도 오류를 던지지 않기 때문이다.

 

반응형

'프로그래밍 > Javascript' 카테고리의 다른 글

prototype  (0) 2018.12.20
javascript containsAll  (1) 2016.11.04
[jquery] hide, show 함수, visibility 속성  (0) 2016.10.28
jquery crossdomain ajax jsonp  (1) 2015.10.30
한글, 영문 check  (0) 2011.12.27

+ Recent posts