1. JavaScript 定义了几种数据类型?哪些是原始类型?哪些是复杂类型?原始类型和复杂类型的区别是什么?
1.1 JavaScript 定义了六种数据类型?
- 数值(number):整数和小数(比如1和3.14)
- 字符串(string):字符组成的文本(比如"Hello World")
- 布尔值(boolean):true(真)和false(假)两个特定值
- undefined:表示“未定义”或不存在,即此处目前没有任何值
- null:表示空缺,即此处应该有一个值,但目前为空
- 对象(object):各种值组成的集合
1.2 哪些是原始类型?哪些是复杂类型?
- 数值、字符串、布尔值称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再对齐进行细分
- 对象为复杂类型(complex type)的值,一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。
- undefined和null,一般将它们看成两个特殊值。
对象又可以细分为三个子类型:
- 狭义的对象(object)
- 数组(array)
- 函数(function)
- 正则表达式 (regexp)
1.3 原始类型和复杂类型的区别是什么?
1.3.1 特性区别:
- 原始值是固定而简单的值,是存放在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置.原始值是表示Javascript中可用的数据或信息的最底层形式或最简单形式。原始类型的值被称为原始值,是因为它们是不可细化的。也就是说,数字是数字,字符是字符,布尔值则是true或false,null和undefined就是null和undefined。这些值本身很简单,不能表示由其他值组成的值
- 复杂值可以由很多不同类型的javascript对象组成。复杂对象其在内存中的大小是未知的,因为复杂对象可以包含任何值,而不是一个特定的已知值,
1.3.2 存储方式区别
- 原始值占据空间固定,是简单的数据段,为了便于提升变量查询速度,将其存储在栈(stack)中
- 由于复杂值的大小会改变,所以不能将其存放在栈中,否则会降低变量查询速度,因此其存储在堆(heap)中,存储在变量处的值是一个指针,指向存储对象的内存处
1.3.3 访问方式的区别
- 按值访问
原始值是作为不可细化的值进行存储和操作的,引用它们会转移其值 - 引用访问
复杂值是通过引用进行存储和操作的,而不是实际的值。创建一个包含复杂对象的变量时,其值是内存中的一个引用地址。引用一个复杂对象时,使用它的名称(即变量或对象属性)通过内存中的引用地址获取该对象值
1.3.4 比较方式的区别
- 原始值采用值比较,而复杂值采用引用比较。复杂值只有在引用相同的对象(即有相同的地址)时才相等。即使是包含相同对象的两个变量也彼此不相等,因为它们并不指向同一个对象
1.3.5 动态属性的区别
- 对于复杂值,可以为其添加属性和方法,也可以改变和删除其属性和方法;但简单值不可以添加属性和方法
复杂值支持动态对象属性,因为我们可以定义对象,然后创建引用,再更新对象,并且所有指向该对象的变量都会获得更新。一个新变量指向现有的复杂对象,并没有复制该对象。这就是复杂值有时被称为引用值的原因。复杂值可以根据需求有任意多个引用,即使对象改变,它们也总是指向同一个对象
1.3.6 包装类型的区别
- 原始值被当作构造函数创建的一个对象来使用时,Javascript会将其转换成一个对象,以便可以使用对象的特性和方法,而后抛弃对象性质,并将它变回到原始值
2. typeof和instanceof的作用和区别?
2.1 typeof运算符可以返回一个值的数据类型,可能有以下结果。
- 原始类型: 数值、字符串、布尔值分别返回number、string、boolean。
- 函数: 返回function
- undefined: 返回undefined。
- 除此以外,其他情况都返回object
2.2 instanceof的作用
instanceof用于判断某个变量是否是某个对象的实例,返回值为true或false
3. 如何判断一个变量是否是数字、字符串、布尔、函数
typeof 变量名
如果返回值为number, 表示变量为数值;
如果返回值为string, 表示变量为字符串;
如果返回值为boolean, 表示变量为布尔运算;
如果返回值为function, 表示变量为函数;
4. NaN是什么? 有什么特别之处?
NaN含义是Not a Number,表示变量类型为数值的非数字;
NaN和任何值都不相等,包括自己
5. 如何把非数值转化为数值?
有三个函数可以把非数值转换为数值
- Number()
- parseInt()
- parseFloat()
其中利用parseInt()及parseFloat()进行转换是会按照以下规则: - 忽略字符串前面的空白字符,找到第一个非空白字符
- 如果第一个字符不是-或者数字返回NaN
- 如果是继续解析,直到非数值模式为止
- 0开头会当做八进制,0x开头会当做十六进制,但是可以指定第二个参数指定基数
6. " == "与 " === " 有什么区别
相等运算符" == "比较两个值是否相等,严格相等运算符" === "比较它们是否为“同一个值”。如果两个值不是同一类型,严格相等运算符" === "直接返回false,而相等运算符" == "会将它们转化成同一个类型,再用严格相等运算符进行比较。
7. break与continue有什么区别
- break语句用于跳出代码块或循环。执行该代码块或循环的之后的内容
- continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环的执行
8. void 0 和 undefined在使用场景上有什么区别
void运算符的作用是执行一个表达式,然后不返回任何值,或者说返回undefined。
在函数中,undefined可以被赋值,此时如果需要判断一个变量为undefined,可以采用 "变量 = void 表达式"的方式来判断
9. 以下代码的输出结果是?为什么?
console.log(1+1); // 2
console.log("2"+"4"); // 24
console.log(2+"4"); // 24
console.log(+"4"); // 4
10. 以下代码的输出结果是?
var a = 1; //声明变量 a,且a = 1;
a+++a; // (a++)+a=1 + 2 = 3
typeof a+2; // (typeof a)+2 = "number"+2 = number2
11. 以下代码的输出结果是? 为什么
var a = 1; // 变量 a = 1
var b = 3; // 变量 b = 3
console.log( a+++b ); // a+++b=(a++)+b=1 + 3 = 4, a=2, b=3
12. 遍历数组var arr = [3,4,5],把数组里的打印数组每一项的平方
for(var i=0; i<arr.length; i++) {
console.log(arr[i]*arr[i])
}
13. 遍历 JSON, 打印里面的值
var obj = {
name: 'hunger',
sex: 'male',
age: 28
}
for(var key in obj){
console.log(obj[key])
}
14. 以下代码输出结果是? 为什么 (选做题目)
var a = 1, b = 2, c = 3;
var val = typeof a + b || c >0
console.log(val) // number2
/*
val = ((typeof a) + b) || (c >0)
number2 || true
第一个运算子值为字符串,true,返回第一个运算子的值,即 number2
*/
var d = 5;
var data = (d ==5) && console.log('bb')
console.log(data) // bb
/*
var data = (d ==5) && console.log('bb')
(d ==5)运算值为true,data返回第二个运算子的值,即bb
*/
var data2 = d = 0 || console.log('haha')
console.log(data2) // haha
/*
data2 = d = 0 || console.log('haha')
data2 = 0, 布尔运算false,正式返回第二个运算子的值,即 haha
*/
var x = !!"Hello" + (!"world", !!"from here!!");
console.log(x) // 2
/*
true + ( false, true)
true + true
返回值 2
*/