数据类型

image.png
image.png

  1. B选项。
  • 任何数值除以0都会导致错误而终止程序执行。但是在 JavaScript 中,会返回出特殊的值,因此不会影响程序的执行。
  • 比0大的数除以0,则会得到无穷大,所以 js 用 Infinity 来显示出来。
  • 也就是1/0得到的是Infinity。
  • isNaN(1/0)返回的是false。但是isNaN(0/0)返回的就是true
  1. C选项。
  • in操作符,对于数组属性需要指定数字形式的索引值来表示数组的属性名称(固有属性除外,如length)。
  • 所以说在这里,1 in [1]并不是表示数字1在不在数组里。而是表示数组中含不含有1这个索引index值。
    数组长度为1,所以只含有的index值为0,这个表达式返回fasle。

image.png
变量a为number类型,属于基本数据类型,基本数据类型在传参时,通过拷贝值进行传递
因此,在函数内部修改形参时,不会对实参产生影响,故输出a的值为10。

数组

解构赋值

  1. for(let i=0;i<12;i++){} console.log(i);
  2. const a = 12;a=13;
  3. console.log(a);
  4. const g = {b:3};
  5. console.log(g.b);
  6. g.b=12;console.log(g.b);
  7. let [head,...tail] = [1,2,3,4];
  8. conole.log(tail);
  9. //i not defined,TypeError,3,12,[2,3,4]

1.let 与var不同,存在块级作用域,在for循环中声明,循环之外销毁 所以 i not defined
2.const 声明一个常量无法更改,所以TypeError
3.const 声明的是一个常量所以是无法更改的
如果const出来的是一个对象他的属性是可以更改的。
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
以前,为变量赋值,只能直接指定值。
var a = 1; var b = 2; var c = 3;
ES6允许写成下面这样。

  1. var [a, b, c] = [1, 2, 3];
  2. let [foo, [[bar], baz]] = [1, [[2], 3]];
  3. foo // 1 bar // 2 baz // 3
  4. let [x, , y] = [1, 2, 3];
  5. x // 1 y // 3
  6. let [x, y, ...z] = ['a'];
  7. x // "a" y // undefined z // []
  8. let [head, ...tail] = [1, 2, 3, 4];
  9. head // 1 tail // [2, 3, 4]
  10. let [ , , third] = ["foo", "bar", "baz"];
  11. third // "baz"

上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

如何判断为数组

A:Array 为 js 的原生对象,它有一个静态方法:Array.isArray(),能判断参数是否为数组
JavaScript 语法题 - 图4
B:instanceof运算符返回一个布尔值,表示对象是否为某个构造函数的实例(题目中 instance of , emem)JavaScript 语法题 - 图5
C: typeof 能判断类型有:number、string、boolean、symbol、undefined、function;
object、array、null 的变量都返回 object
D:Object.prototype.toString() 为 Object 对象的实例方法,默认情况下(即不重写该方法),返回参数的类型字符串。
JavaScript 语法题 - 图6

对象

  1. let obj = {
  2. num1: 117
  3. }
  4. let res = obj;
  5. obj.child = obj = { num2: 935 };
  6. var x = y = res.child.num2;
  7. console.log(obj.child);
  8. console.log(res.num1);
  9. console.log(y);

undefined、117、935

this

1)当在函数调用的时候指向widow
2)当方法调用的时候指向调用对象
3)当用apply和call上下文调用的时候指向传入的第一个参数
4)构造函数调用指向实例对象

  1. var obj ={
  2. a:1,
  3. b:function () {
  4. alert(this.a)
  5. }
  6. };
  7. var fun = obj.b;
  8. fun();
  9. // 输出undefined
  10. // 虽然fun是obj.b的一个引用,但是实际上,它引用的是b函数本身,因此此时的fun()
  11. // 其实 是一个不带任何修饰的函数调用,所以this指向window。
  1. var obj = {};
  2. obj.log = console.log;
  3. obj.log.call(console,this);
  4. obj.log = console.log;
  5. //在本行中obj对象中创建了一个函数(即console.log)的引用log,
  6. //因为是个这个函数的引用如果想要执行可以有两种方法,第一种是后边加(),
  7. //第二种是使用apply()或者call(),二者第一个参数都是this,
  8. //接下来的参数apply是参数数组或者是"arguments",而call的参数是直接的参数值
  9. obj.log.call(console,this);
  10. //如上所述,call的第二个参数是要被传入obj.log()的参数,
  11. //这行代码其实可等价于console.log(this),而因为这三行代码都是在global环境下定义的
  12. //(不是函数中的局部变量),所以this就是window.
  13. //至于第一个参数为什么是console而不是this,我觉得console被按照this处理了,
  14. //我试了试,替换后的执行结果相同

迭代器

  1. function control(x) {
  2. if (x == 3) throw new Error("break");
  3. }
  4. function foo(x = 6) {
  5. return {
  6. next: () => {
  7. control(x);
  8. return {done: !x, value: x && x--};
  9. }
  10. }
  11. }
  12. let x = new Object;
  13. x[Symbol.iterator] = foo;
  14. for (let i of x) console.log(i);

1、什么是迭代器?

迭代器是一个对象,需要满足:对象内部有方法next,next方法要求返回对象{done: true或false, value:值 }
!!!(注意区分:迭代器 和可迭代对象 是不一样的)

2、一个迭代器是如何遍历的?

  1. constarr = ["a","b"]
  2. // 数组默认是一个可迭代对象,就好比题目中的对象x
  3. constiterator = arr[Symbol.iterator]() // 拿到迭代器
  4. console.log(iterator.next());
  5. console.log(iterator.next());
  6. // { value: 'a', done: false }
  7. // { value: 'b', done: false }
  8. // { value: undefined, done: true }

不难看出,value表示每次遍历的值,而done表示遍历是否完成。

3、for…of…补充

for… of…的使用需要是一个可迭代对象,这道题的x,也是因为是一个可迭代对象,所以才可以用的for…of
可以理解为:for..of..就是上面调用iterator.next()的语法糖,直到最后done为true表示遍历完了。…

4、什么是可迭代对象?

如果一个对象,实现了[Symbol.iterator]方法,且这个方*返回一个迭代器(这个方法就是一个生成迭代器的函数,比如题目中的foo函数)

  1. function foo(x = 6) {
  2. return{ // 返回一个迭代器
  3. next: () => {
  4. control(x);
  5. return{done: !x, value: x&&x-- };
  6. }
  7. }
  8. }
  9. // x成为可迭代对象
  10. x[Symbol.iterator] = foo

5、得结果

  1. for(let i of x) console.log(i);

既然x是可迭代对象,那他可以用for…of…进行遍历,遍历时会自动去执行foo,foo返回迭代器。
上面也说了for…of…的遍历就是:一次次的调用iterator的next,拿到value,直到next返回的done为true。

  1. function foo(x = 6) {
  2. return {
  3. next: () => {
  4. control(x);
  5. return {done: !x, value: x && x--};
  6. }
  7. }
  8. }

里层next函数调用的x是foo的参数x(闭包),x默认赋值为6,通过题目中的control函数可以知道,x=3的时候,就抛错,结束了。
当x=6,return{ done:!x, value: x && x—}
done为false,value是x && x—
6 && 6, &&前者为true,value结果取后者,return { done:false, value : 6},
然后x—变成5
继续。。。。最后结果
6,5,4,抛错

闭包

  1. function outer(){
  2. var num = 0;
  3. function inner(){
  4. num++;
  5. console.log(num);
  6. }
  7. return inner;
  8. }
  9. var f1 = outer();
  10. f1();
  11. f1();
  12. var f2 = outer();
  13. f2();
  14. f2();
  15. // 1 2 1 2

闭包变量为num,内部函数inner可以访问到外部函数outer的num变量,这相当于授权该变量可以被延迟使用,每次调用外部函数时,都会开辟相应的内存空间,闭包变量num会保存在该内存空间中,直到该外部函数的内存空间被销毁。
在本题中,调用外部函数outer时开辟一个内存空间,变量num保存在该内存空间中,因此两次调用f1的输出结果为1 2;当再次调用外部函数outer时,又重新创建一个内存空间,因此两次调用f2的输出结果同样为1 2。

Javascript 预处理

Javascript分为预处理阶段和执行阶段,尽管if里面的语句不会被执行,但是在预处理阶段还是会将其提升,因此最终还是undefined。

  1. var a = 1;
  2. function test() {
  3. console.log(a);
  4. if(false) {
  5. var a = 2;
  6. }
  7. }
  8. test();
  9. ————————————————————————————————————————————————————————————————————————————————————
  10. //其实代码执行过程如下:
  11. var a
  12. a = 1;
  13. function test() { //函数会先去找自己内部的变量,内部有就不会往外面找,内部没有才去外面找
  14. var a; //变量提升
  15. console.log(a);
  16. if(false) { //因为false没有满足if的条件,所以不能进入if语句里进行赋值
  17. a = 2; //if语句的条件把false改成true,就可以进入if语句赋值
  18. }
  19. }
  20. test();
  21. // 因此最终输出undefined

promise

:::warning 三个状态 pending fulfilled rejected
两个过程 pending->fulfilled(resolve) pending->rejected(reject)
一个方法 then :::

  • 一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
  • 一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换
  • promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致
  • then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。