이 글의 내용은 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_obj
,out_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 }질문이 있으신가요? 함수 매개변수가 값으로 전달되지 않나요? 함수 내부의 처리가 외부에 반영되는 이유는 무엇입니까? 이건 슈퍼, 슈퍼, 슈퍼 오해입니다.
우선 우리의 관점을 바로잡아야 합니다. 즉, 함수 매개변수가 값으로 전달된다는 것입니다.
그럼 여기서는 무엇을 이해하시나요? 참조 유형의 경우 참조 유형은 참조와 실제 메모리 공간으로 구분된다고 앞서 말했습니다. 여기서 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!