The content of this article is about the analysis of JavaScript data types and variables (with examples). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
In this article, let’s talk about data types and variables in JS. This is the most basic type of question when learning JS, but it is an important one. I hope my sharing is helpful to you.
At the beginning of the article, I will first mention a few questions encountered in the interview:
For example:
How to understand the passing of parameters by value?
What is a temporary dead zone?
What is variable promotion?
What is the difference between global variables and window properties? Why?
... ...
The style of this article is to analyze knowledge points while inserting some interview questions that I have experienced.
In JS, there are 6 basic data types, namely numerical values, strings, Boolean values, null, undefined, and Symbol.
For basic data types, what we need to understand is: the storage method of basic types in memory is a stack. Each value is stored separately and does not affect each other.
Basic types are accessed by value. When comparing, compare by value:
1 === 1 // true
The value of the reference type is stored in the heap, while the reference is stored in the stack.
Reference types are accessed by reference. When comparing, the reference is also compared:
{} === {} // => false
In JS, parameters can be any type of value, even functions.
What needs to be analyzed here is which type of parameters are passed? Reference type or primitive type?
Let’s look at a basic example:
var out_num = 1; function addOne(in_num) { in_num += 1; return in_num; } addOne(out_num); // => 2 out_num // => 1
In this example, we pass an actual parameter out_num to the addOne() function. At this time, out_num will be passed to in_num, that is, there is an internal in_num = out_num
process. The final result we see is that out_num has not been changed by the function, indicating that in_num and out_num are two values stored independently in memory, that is, passed by value.
Let’s look at another transformation:
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 }
The question is coming? Aren't function parameters passed by value? Why is the processing inside the function reflected outside? This is a super super super misunderstanding.
First of all, we still have to correct our point of view, that is, function parameters are passed by value. How do you understand this? For reference types, it was said earlier that reference types are divided into references and actual memory space. Here out_obj is still passed to in_obj, that is, in_obj = out_obj
, out_obj and in_obj are two references. They are stored in memory independently, but they point to the same memory.
And in_obj.value = 1
is the actual object of direct operation. Changes to the actual object will be synchronized to all references that refer to the actual object.
If you look at this example again, it may become clearer.
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 }
You only need to grasp one point: the assignment of an object will cause the actual object pointed to by the reference to change.
There are usually three specific methods to determine the data type:
1. typeof operator
The typeof operator returns a string representing the data type. It has the following obvious flaws:
typeof null // => 'object' typeof [] // => 'object'
This is because of the bugs left at the beginning of the JS language design. You can read this article http://2ality.com/2013/10/typ... to learn more about typeof's handling of null.
So typeof is best used to determine some basic types, such as numeric values, strings, Boolean values, undefined, and Symbol.
2. Behind the instanceof operator
typeof is to judge the data type by judging type tags, while instanceof is to judge the constructor Whether the prototype appears anywhere on the object's prototype chain.
For example:
{} instanceof Object // => true [] instanceof Array // => true [] instanceof Object // => true
Also determine the custom type:
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
So, for the basic data type in the form of literal, it cannot be determined by instanceof:
1 instanceof Number // => false Number(1) instanceof Number // => false new Number(1) instanceof Number // => true
3. Object.prototype.toString()
This is currently the most recommended method, which can more accurately and accurately determine any data type, even JSON, regular , dates, errors, etc. In Lodash, the core of determining data type is also the Object.prototype.toString() method.
Object.prototype.toString.call(JSON) // => "[object JSON]"
For the principle behind this, you can read this article http://www.cnblogs.com/ziyunf...
4. Others
The above three This is a general method of determining data type. Questions such as how to judge an array, how to judge NaN, how to judge array-like objects, and how to judge an empty object will also appear during the interview. This type of problem is relatively open, and the solution is usually to grasp the core characteristics of the judgment data.
For example: judging array-like objects.
你先要知道 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 创建的全局属性则不会。这是现象,通过现象看本质,二者本质上的区别在于:
The value of the [[configurable]] data attribute of a global variable declared using var is false and cannot be deleted by delete. The default value of [[configurable]] for attributes created directly on the object is true, that is, they can be deleted by delete. (About the [[configurable]] attribute, it will be mentioned when analyzing objects in later articles)
In this article"Data types and variables 》In the article, 7 major categories were analyzed. Let’s review:
Basic types, reference types, parameter transfer methods, how to determine data types, how to convert data types, variable promotion and temporary dead zones, and declaring global variables.
These are not only high-frequency test points in school recruitment interviews, but also essential knowledge points for learning JS.
Tip1: There is a reason why the book "JavaScript Advanced Programming" is called the "Front-End Bible". It is very necessary for you who are preparing for campus recruitment! Read the book a hundred times, and its meaning will become apparent. You will find that most of the JS-related knowledge points you encounter in the interview can be found in this book!
Tip2: In the process of preparing for review, pay attention to the modularity and correlation of knowledge. You must have the ability to divide knowledge modules yourself, such as today's "Data Types and Variables" module. Relevance means that any knowledge is related, for example, it involves modules such as scope and memory.
The above is the detailed content of Analysis of JavaScript data types and variables (with examples). For more information, please follow other related articles on the PHP Chinese website!