>  기사  >  웹 프론트엔드  >  JavaScript 데이터 유형 및 변수 분석(예제 포함)

JavaScript 데이터 유형 및 변수 분석(예제 포함)

不言
不言앞으로
2018-11-15 17:07:012066검색

이 글의 내용은 JavaScript 데이터 유형 및 변수 분석에 관한 것입니다(예제 포함). 참고할 만한 가치가 있으니 도움이 필요한 분들에게 도움이 되길 바랍니다.

이 글에서는 JS의 데이터 유형 및 변수에 대해 이야기하겠습니다. JS를 배울 때 가장 기본적인 질문이지만 중요한 질문입니다. 제 공유가 여러분에게 도움이 되기를 바랍니다.

기사 시작 부분에서 인터뷰에서 만난 몇 가지 질문을 먼저 언급하겠습니다.

예:

값에 따른 매개변수 전달을 이해하는 방법은 무엇입니까?

일시적 데드존이란 무엇인가요?

변수홍보란?

전역 변수와 창 속성의 차이점은 무엇인가요? 왜?

... ...

이 글의 스타일은 제가 경험한 면접 질문 몇 가지를 삽입하면서 지식 포인트를 분석하는 것입니다.

기본 데이터 유형

JS에는 숫자값, 문자열, 부울값, null, 정의되지 않음, 기호의 6가지 기본 데이터 유형이 있습니다.

기본 데이터 유형의 경우 우리가 이해해야 할 것은 기본 유형이 메모리에 저장되는 방식이 스택이라는 것입니다. 각 값은 별도로 저장되며 서로 영향을 미치지 않습니다.

기본 유형은 값으로 액세스됩니다. 비교할 때는 값으로 비교하세요:

1 === 1 // true

참조 데이터 유형

참조 유형의 값은 힙에 저장되고 참조는 스택에 저장됩니다.

참조 유형은 참조로 액세스됩니다. 비교할 때 참조도 비교하세요.

{} === {} // => false

매개변수 전달 방법

JS에서 매개변수는 모든 유형의 값, 심지어 함수일 수 있습니다.

여기서 분석해야 할 것은 어떤 유형의 매개변수가 전달되는지 입니다. 참조 유형 또는 기본 유형?

먼저 기본 예제를 살펴보겠습니다.

var out_num = 1;

function addOne(in_num) {
    in_num += 1;
    return in_num;
}

addOne(out_num); // => 2
out_num // => 1

이 예제에서는 addOne() 함수에 실제 매개변수 out_num을 전달합니다. 이때 out_num은 in_num에 전달됩니다. 즉, 내부 in_num = out_num 프로세스. 우리가 보는 최종 결과는 out_num이 함수에 의해 변경되지 않았다는 것입니다. 이는 in_num과 out_num이 메모리에 독립적으로 저장된 두 개의 값, 즉 값으로 전달되었음을 나타냅니다. in_num = out_num 的过程。最后我们看到的结果是 out_num 并没有被函数改变,说明 in_num 和 out_num 是两个在内存中独立存放的值,即按值传递。

再来看一个变形:

var out_obj = { value: 1 };

function addOne(in_obj) {
    in_obj.value += 1;
    return in_obj;
}

addOne(out_obj); // => { value: 2 }
out_obj // => { value: 2 }

问题来了?函数参数不是按值传递吗?为什么这里函数内部的处理反映到外部了?这是一个超级超级超级的理解误区。

首先,我们还是得摆正观点,即函数参数是按值传递的。那这里怎么理解呢?对于引用类型而言,前面说引用类型分为引用和实际的内存空间。在这里 out_obj 依旧传递给 in_obj,即 in_obj = out_objout_obj 和 in_obj 是两个引用,它们在内存中的存储方式是独立的,但是它们却指向同一块内存。

in_obj.value = 1

또 다른 변형을 살펴보겠습니다.

var out_obj = { value: 1 };

function addOne(in_obj) {
    in_obj = { value: 2 };
    return in_obj;
}

addOne(out_obj); // => { value: 2 }
out_obj // => { value: 1 }
JavaScript 데이터 유형 및 변수 분석(예제 포함)질문이 있으신가요? 함수 매개변수가 값으로 전달되지 않나요? 함수 내부의 처리가 외부에 반영되는 이유는 무엇입니까? 이건 슈퍼, 슈퍼, 슈퍼 오해입니다.

JavaScript 데이터 유형 및 변수 분석(예제 포함)

우선 우리의 관점을 바로잡아야 합니다. 즉, 함수 매개변수가 값으로 전달된다는 것입니다.

그럼 여기서는 무엇을 이해하시나요? 참조 유형의 경우 참조 유형은 참조와 실제 메모리 공간으로 구분된다고 앞서 말했습니다. 여기서 out_obj는 여전히 in_obj로 전달됩니다. 즉, in_obj = out_obj입니다.

out_obj와 in_obj는 독립적으로 메모리에 저장되지만 동일한 메모리를 가리킵니다.

그리고 in_obj.value = 1은 직접 연산의 실제 객체입니다. 실제 개체에 대한 변경 사항은 실제 개체를 참조하는 모든 참조에 동기화됩니다.

이 예를 다시 보면 더 명확해질 수 있습니다.

typeof null // => 'object'

typeof [] // => 'object'
한 가지만 파악하면 됩니다. 객체를 할당하면 참조가 가리키는 실제 객체가 변경됩니다.

데이터 유형을 결정하는 방법

데이터 유형을 결정하는 데에는 일반적으로 세 가지 특정 방법이 있습니다.

1. typeof 연산자

typeof 연산자는 데이터 유형을 나타내는 문자열을 반환합니다. 다음과 같은 명백한 결함이 있습니다.

{} instanceof Object // => true

[] instanceof Array // => true
[] instanceof Object // => true
이는 JS 언어 설계 초기부터 남아있는 버그 때문입니다. typeof의 null 처리에 대해 자세히 알아보려면 http://2ality.com/2013/10/typ... 기사를 읽어보세요.

그래서 typeof는 숫자 값, 문자열, 부울 값, 정의되지 않음 및 기호와 같은 일부 기본 유형을 결정하는 데 가장 적합합니다.

2.instanceof 연산자

typeof는

type 태그

를 판단하여 데이터 유형을 판단하는 반면, instanceof는 생성자의 프로토타입이 객체 프로토타입 체인의 어느 곳에나 나타나는지 여부를 판단합니다.

예:

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
var auto = new Car('Honda', 'Accord', 1998);

console.log(auto instanceof Car);
// => true

console.log(auto instanceof Object);
// => true
또한 사용자 정의 유형을 결정합니다:

1 instanceof Number // => false

Number(1) instanceof Number // => false

new Number(1) instanceof Number // => true
따라서 리터럴 형식의 기본 데이터 유형의 경우 다음 인스턴스로 결정할 수 없습니다:
Object.prototype.toString.call(JSON) // => "[object JSON]"

3.

🎜🎜 이는 현재 가장 권장되는 방법으로 JSON, 일반, 날짜, 오류 등 모든 데이터 유형을 보다 정확하고 정확하게 확인할 수 있습니다. Lodash에서 데이터 유형을 결정하는 핵심은 Object.prototype.toString() 메서드이기도 합니다. 🎜
if (isTrue) {
    // ...
} else {}
🎜이에 대한 원리는 http://www.cnblogs.com/ziyunf...🎜🎜4. 기타🎜🎜위의 세 가지가 데이터 유형을 결정하는 일반적인 방법입니다. 🎜배열 판단 방법, NaN 판단 방법, 배열 유사 객체 판단 방법, 빈 객체 판단 방법🎜 등의 질문도 면접 중에 나옵니다. 이러한 유형의 문제는 상대적으로 개방적이며 해결책은 일반적으로 판단 데이터의 핵심 특성을 파악하는 것입니다. 🎜🎜예: 배열과 유사한 객체를 판단합니다. 🎜

你先要知道 JS 中类数组对象是什么样子的,并寻求一个实际的参照物,比如 arguments 就是类数组对象。那么类数组对象具有的特点是:真值 & 对象 & 具有 length 属性 & length 为整数 & length 的范围大于等于 0,小于等于最大安全正整数(Number.MAX_SAFE_INTEGER)。

在你分析特点的时候,答案就呼之欲出了。【注意全面性】

数据类型如何转换

JS 数据类型的动态性将贯穿整个 JS 的学习,这是 JS 非常重要的特性,很多现象就是因为动态性的存在而成为 JS 独有。

正是由于动态性,JS 的数据类型可能在你毫无察觉的情况下,就发生了改变,直到运行时报错。

这里主要分析下面 8 种转换规则。

1、if 语句

if 语句中的类型转换是最常见的。

if (isTrue) {
    // ...
} else {}

在 if 语句中,会自动调用 Boolean() 转型函数对变量 isTrue 进行转换。

当 isTrue 的值是 null, undefined, 0, NaN, '' 时,都会转为 false。其余值除 false 本身外都会转为 true。

2、Number() 转型函数

我们重点关注 null undefined 以及字符串在 Number() 下的转换:

Number(null) // => 0
Number(undefined) // => NaN
Number('') // => 0
Number('123') // => 123
Number('123abc') // => NaN

注意和 parseInt() 对比。

3、parseInt()

parseInt(null) // => NaN
parseInt(undefined) // => NaN
parseInt('') // => NaN
parseInt('123') // => 123
parseInt('123abc') // => 123

4、==

这里需要注意的是:

null == undefined // => true

null == 0 // => false
undefined == false // => false

null 与 undefined 的相等性是由 ECMA-262 规定的,并且 null 与 undefined 在比较相等性时不能转换为其他任何值。

5、关系操作符

对于两个字符串的比较,是比较的字符编码值:

'B'  true

一个数值,另一个其他类型,都将转为数字进行比较。

两个布尔值转为数值进行比较。

对象,先调用 valueOf(),若不存在该方法,则调用 toString()。

6、加法

加法中特别注意的是,数字和字符串相加,将数字转为字符串。

'1' + 2 => // '12'
1 + 2 => // 3

对于对象和布尔值,调用它们的 toString() 方法得到对应的字符串值,然后进行字符串相加。对于 undefined 和 null 调用 String() 取得字符串 'undeifned' 和 'null'。

{ value: 1 } + true // => "[object Object]true"

7、减法

对于字符串、布尔值、null 或者 undefined,自动调用 Number(),转换结果若为 NaN,那么最终结果为 NaN。

对于对象,先调用 valueOf(),如果得到 NaN,结果为 NaN。如果没有 valueOf(),则调用 toString()。

8、乘法、除法

对于非数值,都会调用 Number() 转型函数。

变量提升与暂时性死区

JS 中有三种声明变量的方式:var, let, const。

var 声明变量最大的一个特点是存在变量提升。

console.log(a); // undefined
var a = 1;
console.log(a); // 1

第一个打印结果表示,在声明变量 a 之前,a 就已经可以访问了,只不过并未赋值。这就是变量提升现象。(具体原因,我放在后面分析作用域的时候来写)

let 和 const 就不存在这个问题,但是又引入了暂时性死区这样的概念。

/**
* 这上面都属于变量 a 的暂时性死区
* console.log(a) // => Reference Error
*/
let a = 1;
console.log(a); // => 1

即声明 a 之前,不能够访问 a,而直接报错。

而暂时性死区的出现又引出另外一个问题,即 typeof 不再安全。你可以参考这篇文章 http://es-discourse.com/t/why...

补充:一个经典面试题

for (var i = 0; i <p>我先不再这里展开分析,我打算放到异步与事件循环机制中去分析。不过这里将 var 替换成 let 可以作为一种解决方案。如果你有兴趣,也可以先去分析。</p><p>对于 const,这里再补充一点,用于加深对基本类型和引用类型的理解。</p><pre class="brush:php;toolbar:false">const a = 1;
const b = { value: 1 };

a = 2; // => Error
b.value = 2; // => 2
b = { value: 2 }; // => Error

本质上,const 并不是保证变量的值不得改动,而是变量指向的内存地址不得改动。

声明全局变量

直接通过 var 声明全局变量,这个全局变量会作为 window 对象的一个属性。

var a = 1;
window.a // => 1

在这里提出两个问题,一是 let 声明的全局变量会成为 window 的属性吗?二是 var 声明的全局变量和直接在 window 创建属性有没有区别?

先来回答第一问题。let 声明的全局变量不会成为 window 的属性。用什么来支撑这样的结论呢?在 ES6 中,对于 let 和 const 声明的变量从一开始就形成封闭作用域。想想之前的暂时性死区。

第二个问题,var 声明的全局变量和直接在 window 创建属性存在着本质的区别。先看下面的代码:

var a = 1;
window.a // => 1

window.b = 2;

delete window.a
delete window.b

window.a // => 1
window.b // => undefined

我们可以看到,直接创建在 window 上的属性可以被 delete 删除,而 var 创建的全局属性则不会。这是现象,通过现象看本质,二者本质上的区别在于:

var를 사용하여 선언한 전역 변수의 [[configurable]] 데이터 속성 값이 false이므로 삭제로 삭제할 수 없습니다. 객체에 직접 생성된 속성에 대한 [[configurable]]의 기본값은 true입니다. 즉, 삭제를 통해 삭제할 수 있습니다. ([[configurable]] 속성에 대해서는 이후 글에서 객체 분석 시 언급하겠습니다)

요약

"데이터 유형 및 변수"글에서는 7가지 주요 범주가 분석됩니다. 검토해 보겠습니다:

기본 유형, 참조 유형, 매개변수 전송 방법, 데이터 유형 결정 방법, 데이터 유형 변환 방법, 변수 승격 및 임시 데드존, 전역 변수 선언.

학교채용 면접에서 많이 나오는 시험 포인트일 뿐만 아니라, JS를 배우기 위한 필수 지식 포인트이기도 합니다.

Tip1: "자바스크립트 고급 프로그래밍"이라는 책을 "프론트엔드 바이블"이라고 부르는 이유가 있습니다. 캠퍼스 리크루팅을 준비하는 당신에게 꼭 필요한 내용입니다! 책을 백 번 읽으면 그 의미가 분명해질 것입니다. 인터뷰에서 접하게 되는 JS 관련 지식 포인트는 대부분 이 책에서 만나보실 수 있습니다!

Tip2: 리뷰를 준비하는 과정에서 지식의 모듈성과 상관성에 주의하세요. 오늘날의 "데이터 유형 및 변수" 모듈과 같은 지식 모듈을 스스로 분할할 수 있는 능력이 있어야 합니다. 관련성은 모든 지식이 관련되어 있음을 의미합니다. 예를 들어 범위 및 메모리와 같은 모듈이 포함됩니다.

위 내용은 JavaScript 데이터 유형 및 변수 분석(예제 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제