珠峰培训 - 第二天课后作业及解析(FruitJ)
文章目录
- 珠峰培训 - 第二天课后作业及解析(FruitJ)
- 一、问答题
- 1. JS中常用的数据类型有哪些 ?
- 2. 浏览器中常用的内核有哪些 ?
- 3.数据类型之间的区别 ?
- 4. 列举常用的关键字和保留字
- 5. JS中创建变量的几种常用方式 ?
- 二、练习题
- 1. 写出下面结果输出的答案 (阿里面试题)
- 2. 分别写出下列表达式输出的结果 (腾讯面试题)
- 3. 写出下列代码的输出结果 (腾讯面试题)
- 4. 写出下列代码的输出结果 (腾讯面试题)
- 5. 能输出”1”的有哪些?
- 6. 下面结果是”undefined”的是
- 7. 下面结果能得到true的是
- 8. 输出下面程序的结果
- 9. 下面程序输出的结果
- 10. 下面程序输出的结果
- 三、扩展题
- 1. 浏览器常用的输出方式,除了console.log还有哪些?
- 2. < script > 标签放到页面头部和尾部的区别,以及解决办法 ?
一、问答题
1. JS中常用的数据类型有哪些 ?
2. 浏览器中常用的内核有哪些 ?
内核 | 常用浏览器 | 前缀 |
Webkit | Chrome 28 以前、Safari 、android 默认自带浏览器 | -webkit- |
Gecko | FireFox | -moz- |
Presto | Opera 15 以前 | -o- |
Trident | IE 6~7 | -ms- |
Blink | Chrome 28 及以后、Opera 15及以后 | -webkit- |
Webkit + Trident | 国内大部分双核浏览器 | -webkit- |
3.数据类型之间的区别 ?
- JavaScript 中数据类型分为
基本数据类型
、引用数据类型
、基本数据类型的包装类型
基本数据类型
与引用数据类型
之间的区别 :
-1). 基本数据类型的值在浏览器内存模型中存储在栈
空间。
引用数据类型的值在浏览器内存模型中存储在堆
空间。
-2). 由-1).
可知 :
一个基本数据类型变量只能对应栈空间的一个值, 所以变量的复制是本身值 的复制, 即克隆后的变量的值发生改变互不影响。
多个引用数据类型变量可以对应同一个堆空间的一个实例, 所以变量的复制实际上是十六进制的引用地址(指针)
的复制, 最后都指向同一个堆内存中的实例, 即克隆后的变量的属性与方法发生改变时互相影响的。
-3). 基本类型值是不能调用方法的, 但是let str = "Hello World!"; str.replace("H", "h");
并不会抛出异常, 原因就是在代码执行的瞬间, JS 引擎会创建基本类型值的对应的包装类型, 与 “引用类型” 相似, 但不是引用类型, 通过创建包装类型的实例来调用方法并将结果赋值给str
, 然后将包装类型的实例销毁。
-4). 包装类型与引用类型的区别 : 前者是在 js 代码执行的瞬间创建并执行的, 执行完立即销毁, 而引用类型的实例在执行流离开当前作用域之前一直都是存在的(实例的生存期长短不同)。
4. 列举常用的关键字和保留字
关键字 :
do、while、for、continue、break、function、return、arguments、this、new、var、eval、throw、try、catch、finally、with、in、switch、case、typeof、void、debugger、default、if、else
保留字(非严格模式下) :
class、import、export、enum、extends、super
保留字(严格模式下) :
implements、let、package、public、private、protected、interface、instance、static、yield
5. JS中创建变量的几种常用方式 ?
- var、let、const 创建变量 -> 区别 :
-1). var 与 let 和 const 在变量提升层面上有区别(var 有变量提升, let 与 const 没变量提升)
-2). const 与 var 和 let 的区别 : const 定义的是常量, var 与 let 定义的是变量 - function (声明/定义函数)
- import / require (node 环境中导入模块)
- class (创建一个类, 本质上是一个构造函数但与普通的构造函数有区别)
二、练习题
1. 写出下面结果输出的答案 (阿里面试题)
let a = {
n: 1
};
let b = a;
a.x = a = {
n: 2
};
console.log(a.x); // undefined
console.log(b); // { n:1, x: { n: 2 } }
解析 :
此题关键在于这句代码 :
a.x = a = {
n: 2
};
这句代码之前的都好理解,。
-> 浏览器是自上而下, 从左向右执行的。当执行到 a.x
的时候会在堆内存中的 A
实例上定义 x
属性(此时 A
实例有 n:1
和 x
), 然后变量 a
的指针指向了新创建的实例 B
。并且将这个指针(引用地址) 复制给了 a.x
也就是 A 实例的 x
属性, 所以此时 A
实例上有两个属性【n:1 和 x: {n:2}】,
-> console.log(a.x); 访问的是更改指针后的 B
实例上的 x
属性, 此时 B
实例上的属性有【n:2】, 没有 x 所以区默认值 undefined
。
-> console.log(b); 访问的是 A
实例, 所以结果出来了!
2. 分别写出下列表达式输出的结果 (腾讯面试题)
var a = 'abc' + 123 + 456;
var b = '456' - '123';
var c = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false;
console.log(a,b,c); // abc123456, 333, NaNTencentnull9false
此题基础题, 无解析!
3. 写出下列代码的输出结果 (腾讯面试题)
var str = 'abc123';
var num = parseInt(str);
if (num == NaN) {
alert(NaN);
} else if (num == 123) {
alert(123);
} else if (typeof num == 'number') {
alert('number');
} else {
alert('str');
}
// alert("number");
此题基础题, 无解析(num 是 NaN)!
4. 写出下列代码的输出结果 (腾讯面试题)
var a = 0;
var b = a;
b++;
alert(a);
var o = {};
o.a = 0;
var b = o;
b.a = 10;
alert(o.a);
// 先 alert(0) 后 alert(10);
此题基础题, 无解析(b++ 是后置操作, o和b 指向的是堆内存中的同一个实例)!
5. 能输出”1”的有哪些?
A.alert(1)
B.console.log(parseInt(1.3))
C.console.log(1)
D.console.log(isNaN(1))
E.console.log(parseInt("1"))
// A
此题基础题, 无解析( parseIn转型操作默认是向下取整, 1 不是一个 非有效数字
)!
6. 下面结果是”undefined”的是
A.console.log(alert(1))
B.typeof undefined
C.console.log(parseInt(undefined))
D.isNaN(undefined)
// A
此题基础题, 无解析(函数默认返回 undefined) !
7. 下面结果能得到true的是
A.isNaN(null)
B.isNaN(parseInt(null))
C.Number(null)
D.parseFloat(null)
// B
此题基础题, 无解析( A 和 C 是一样的, D 只是转型并没有通过 isNaN 判断) !
8. 输出下面程序的结果
parseInt(""); // NaN
Number(""); // 0
isNaN(""); // false
parseInt(null); // NaN
Number(null); // 0
isNaN(null); // false
parseInt("12px"); // 12
Number("12px"); // NaN
isNaN("12px"); // true
此题基础题, 无解析 !
9. 下面程序输出的结果
if (isNaN(NaN) == "") {
console.log("珠峰");
} else {
console.log("培训"); // 培训
}
此题基础题, 无解析( true 转为数字是 1
, “” 转为数字是 0
) !
10. 下面程序输出的结果
let x = [1, 2, 3];
let y = x;
let z = [4, 5, 6];
y[0] = 10; // [10, 2, 3]
y = z;
z[1] = 20; // [4, 20, 6]
x[2] = z = 30; // [10, 2, 30]
console.log(x, y, z); // [10, 2, 30] , [4, 20, 6] , 30
三、扩展题
1. 浏览器常用的输出方式,除了console.log还有哪些?
方式 | 含义 |
alert | 普通弹框(默认调用 toString 方法将参数序列化) |
console.log | 打印参数日志 |
console.dir | 打印参数详细信息 |
console.table | 以表格的形式打印 |
console.warn | 打印参数的警告信息 |
console.info | 打印参数信息 |
console.error | 打印参数的错误信息 |
confirm | 带有 确定 和 取消 的弹框, 返回值: 确定返回 true, 取消返回 false |
prompt | 在 confirm 基础上给用户选填原因; 返回值: 未填返回 null, 填写返回填写信息 |
console.time/timeEnd | 中间的程序代码执行所消耗的时间 |
.vaule | js 动态表单插值 |
innerText | dom 元素内插入文本值 |
innerHTML | dom 元素内插入文本值或者 dom 节点 |
appendChild | 在父元素下最后一个子节点后面追加一个 dom “碎片” |
insertBefore | 在父元素下给定子节点之前追加一个 dom “碎片” |
2. < script > 标签放到页面头部和尾部的区别,以及解决办法 ?
-
<script>
标签放在头部
和尾部
的异同
:
同 : 不论<script>
标签在头部
或者尾部
都会阻塞页面的渲染。
异 : 虽然不论<script>
标签在头部
或者尾部
都会阻塞页面的渲染, 但是放在头部
不仅阻塞页面解析而且还会阻塞页面的渲染, 而放在尾部
不会阻塞页面的解析仅仅会阻塞页面的渲染。
所以这就导致一个问题 : 如果在头部
执行脚本的时候去获取某个 dom 节点, 但是 js 已经阻塞了页面的解析, dom 结构还未解析就去获取结果会抛出异常, 脚本放在尾部
就不会有这个问题, 因为在尾部执行脚本不会阻塞页面的解析仅会阻塞渲染, 所以使不耽误获取 dom 节点的。 - 解决方案 :
-1). 在尾部
执行脚本
<body>
<script src="Xxx.js"></script>
</body>
-2). 在 头部
执行脚本的时候, 脚本代码用 window.onload = function(){}
包裹。
<head>
<script>
window.onload = function() {
// code ...
};
</script>
</head>
-3). 在 头部
执行脚本的时候使用 script
标签的 defer
属性来更改脚本的执行时机。
<head>
<script src="Xxx.js" defer></script>
</head>
这样脚本就会在页面结构解析完毕后再执行脚本。