js 面试相关

111 阅读35分钟

目录

1、JS基本数据类型中null和undefined区别

2、js有哪八种 数据类型

3、作用域与作用域链

4、闭包

5、js数据类型检测的方式有哪些?

6、instanceOf操作符的实现原理及实现

7、js 中 typeof NaN的结果是什么

8、js 中判断数组的方法

9、js 中操作符什么时候用于字符串的拼接

10、js 中Object.is () 与比较运算符 === 和 == 的区别

11、js中如何进行隐式类型转换

12、 js中的深拷贝和浅拷贝的区别

13、js中与和或操作符的返回值

14、 js 中 == 操作符的强制类型转换规则

15、js中 isNaN 与 Number.isNaN() 的区别

16、es6中的 const 定义的 对象的属性 可以修改吗?

17、ES6中 let、 const 和 var 之问的用法以及区别

18、js中如何的断一个对象是空对象

19、 ES6中new一个箭头函效会怎么样 --->报错

20、js 中对原型的理解

21、js中对原型链的理解

22、 js 对原型的修改和重写

23、for ...of 和 for ... in 的区别

24、js 中如何判断 一个属性 是属于实例对象 还是继承与构造函数

25、js 中bind 和call 、apply 的作用以及他们的区别

26、es6 对 promise 的理解以及他的实例方法

27、什么是回调地狱(多个串联的异步操作)以及如何使用Promise解决

28、ES6中对Promise.all的理解以及应用场景

29、ES6中Promise.race的用法以及使用场景

30、 ES6中使用Promise封装ajax

31、Js中ajax(Async Javascript and XML)的原理是什么?如何实现

32、Js中localstorage和sessionStorage的区别

33 、js中的事件流

34、js如何阻止事件冒泡和默认行为

35、js实现函数的防抖

36、js实现函数的节流

37、对箭头函数的理解

38、Js中1ocalstorage和IsessionStorage的区别

39、js对事件代理的理解以及有用场景

40、jS中对 作用域 和 作用域链 的理解(查找变量)

41、js清空数组的方法

42、js如何实现继承

43、js事件循环机制

44、事件的冒泡和捕获机制

45、防抖和节流

46、promise相关


1、JS基本数据类型中null和undefined区别

// 基本数据类型中null和undefined的区别以及应用:
// 都是代表没有值
/*
null表示“没有对象”,  该处不应该有值
undefined表示“缺少值”, 该处应该有值,但是还没有定义
转为数值也不同,null转为数值为e,undefined转为数值NaN(不是一个数字)
*/

console.log(Number(null));
console.log(Number(undefined));

/*
什么时候会有null:
1、作为函数的参数,表示该函数的参数不是对象
2、作为对象原型链的终点
什么时候会出现undefined:
1、变量被声明了。但是没有赋值,就等于undefined.
2、调用函数时,应该提供的参数没有提供,该参数就等于undefined。
3、对象没有赋值的属性,该属性的值为undefined。
4、函数没有返回值时,默认返回undefined。
*/

console.log(object.getPrototypeof(object.prototype));
var a;
console.log(a)

2、js有哪八种 数据类型

javascript有哪些数据类型,它们的区别?
总共有八种:
基本数据类型: string/number/boolean/null/undefined/BigInt/symbo1(代表创建之后独一无二并且不可变的数据类型)
引用数据类型: object

/* 区别
1、声明变量时的存储分配
基本数据类型 存储在栈中,var a=10
引用数据类型 存储在堆中, var arr=[1,2,3,4,5,...]
2、不同的内存分配机制也带来了不同的访问机制
不可以直接访问堆内存空间的位置以及直接操作堆内存空间,只能操作对象在栈内存中引用地址基本数据类型直接访问到,引用数据类型访问引用地址,根据引用地址找到堆中实体
3、复制变量时的不同
基本数据类型:var a=1,var b=a,将原始值的副本赋值新的变量
引用数据类型:var obj={name:'张三"}, var obj1=obj,将引用地址赋值给新的变量
*/

var a=[1,2,3,4,5];
var b=a;
var c=a[0];
console.log(b);  //[1,2,3,4,5]
console.log(c); //改变数值 1
b[4]=6;
c=7;
console.log(a[4]); //[1,2,3,4,6]
console.log(a[0]); // 1

3、作用域与作用域链

// 全局
 let name= ' 你好啊 '
 // 声明变量  js  
 1: let name  => 作用域集合中,有继续,没有添加这个name属性 
 2:执行name= ‘你好啊’ ,在运行时赋值

console.log(name)  // 变量提升 声明的变量没有赋值,为undefined
var name=' 你好啊 '

// 局部作用域
function fun(){   
     let name= ' 你好啊 '
     console.log(name) // 你好啊
}
fun ()

let name2 =' 悟空1'
function fun(){
     console.log(name2)
}
fun()   //悟空1

// 全局: name2 fun()  局部: name2
// 作用域: 就是一个规则 用来查找变量
// 作用域链:多层嵌套作用域

let d = 4
function fn(){
let c = 3 + d
    console.log(c)  // 7
function fn1(){
let b = 2 + d  // 6
        console.log(b)  // 6
function fn2() {
let a = 1
}
     }
     fun1()
}
console.log(fn())   // fn()没有返回值,默认返回 undefined
// 面试题
let a =1
let a= 1
function fn1(){
function fn2(){
console.log(a)   // fn2 的作用域里没有a ,找上一级 fn1 a=2
}
function fn3(){
let a= 4
         fn2()
     }
let a= 2    //在 fn2 的作用域里
      return fn3  // 最后执行的是 fn2
}
let fn = fn1()
fn()  // 返回 fn3
//
//全局  a =1   fn1()
//fn1     fn2     fn3  a=2
//fn2
//fn3
let a= 1
function fn1(){
function fn3(){
function fn2(){
console.log(a)//
}
let a   // 没有赋值
fn2()  执行到这里的时候,内存里面已经有一个没有赋值的aa = 4
}
let a= 2
    return fn3()
}
let fn = fn1()
console.log(fn)  // undefined

4、闭包

//概念:
1 函数中返回一个函数
2 函数的声明的作用域和函数使用的作用域不同
//用途:
1 获取私有作用域的中的变量
2 这些变量可以保存到内存中
使用函数内部的变量在函数执行完成后,仍然存活在内存中(延长了局部变量的生命周期) 让函数外部可以操作(读写)到函数内部的数据(变量/函数) 问题:
 1、函数执行完后,函数内部声明的局部变量是否还存在
 2、在函数外部能直接访问函数内部的局部变量吗

function a(){
  let n = 0  //保存到内存中
  function add(){
    n++ 
    return n
  }
  return add
}
let getN = a()
console.log( getN())  //1
// console.log( getN())  //2

5、js数据类型检测的方式有哪些?

1、typeof() **** 检测数据类型的运算符


  console.log("数值"",typeof 10);                  // 数值  number
  console.log("布尔" ,typeof true);                // 布尔 boolean
  console.log("字符串",typeof"你好");             //  字符串 string
  console.log("数组"",typeof []);                 //  数组 object     引用类型
  console.log(""函数"",typeof function O0);      //  函数 function
  console.log("对象"",typeof 0);                 // 对象  object   引用类型
  console.log("undefined",typeof undefined);    // undefined  undefined
  console.log("null"",typeof nul1);             // null  object   基本数据类型   null为0,被识别为0(所有的值在计算机中是以二进制编码存储,浏览器把前三位为0的识别为object对象)

2、instanceof 检测某一个实例是否属于这个类 (不能用来检测 null和 undefined) 可以正确判断对象的类型,内部运行机制 判断他在原型链上能否找到这个类型的原型


 console.log("数值"",10 instanceof Number);              // 数值  false
 console.log("布尔"",true instanceof Boolean);           // 布尔  false
 console.log("字符串","你好’instanceof String);           // 字符串  false
 console.log("数组"",D]instanceof Array);                  // 数组  true
 console.log("函数"",function O)0instanceof Function);   // 函数 true
 console.log(""对象"",0 instanceof 0bject);              // 对象 true

3、constructor 检测实例和类的关系,从而检测数据类型,引用原来构造该对象的函数 (不能用来检测 null和 undefined)


 console.log(“数值”,(10).constructor === Number);                // 数值itrue
 console.log("布尔"",(true) . constructor === Boolean);            //  布尔 true
 console.log("字符串”,(你好:).constructor === String);            //   字符串true
 console.log("数组"",([]).constructor === Array);                  //    数组ltrue
 console.log("函数" ,(function()0).constructor === Function);      //  函数true
 console.log("对象"",(0).constructor === 0bject);                  // 对象 true

4、Object-prototype.tostring.call ()


  var a=Object.prototype.tostring;

 console.log("数值" , a.cal1(10));                    //  数值 [object Number]
 console.log("布尔"", a.cal1(true));                 //  布尔 [object Boolean]
 console.log("字符串", a.call(你好"));               //  字符串 [object String]
 console.log("数组", a.cal1([]));                   //  数组 [object Array]
 console.log("函数" , a.call(function()));          //  函数 [object Function]
 console.log(""对象"", a.cal1(0));                  //  对象 [object object]
 console.log("undefined",a.call(undefined));        //  undefined [object undefined ]
 console.log("null",a.cal1(nul1));                  //  null  [object Null]

6、instanceOf操作符的实现原理及实现

 Jsinstanceof操作符的实现原理以及实现

//  instanceof 操作符 用于判断 构造函数 的 prototype 属性是否出现在对象的原型链中的任何位置。
console.log(0 instanceof objecty);
// 构造函数  相当于一个类
function Person(name){
      this. name= name
}
let obj= new Person(' 张三 'console.log( Object.getPrototypeOf(obj) )        // 
console.log( Object.prototype )    //打印原型
console.log( Object.getPrototypeOf(obj)===Object.prototype )    // true
console.log(obj instanceof Person ):  // true
console.log(obj instanceof Object ):  // true
console.1og(object.getPrototypeof(object.getPrototypeof(obj))===Object.prototype);   // true

手写实现原型链的实现原理:

function instance(left,right){       //   获取对象的原型
 let proto = object.getPrototypeof(left);  //  获取构造函数的 prototype  属性
 let prototype= right.prototype;     
while(true) {  //判断原型能不能获取到 
  if( !proto) {  // 取不到返回 false 
     return false       
  }       
  if(proto===prototype){  // 判断对象的原型和构造函数的原型 相等 
     return true      
  } // 如果没有找到,就继续在原型链上找       
  proto = object.getPrototypeOf(proto)    
 }  
}

7、js 中 typeof NaN的结果是什么

//   NaN ( not a number ) 不是一个数字 ,表示是否属于number类型的一种状态,是或否,不是确切的值
//   js中 number 数据类型除了浮点型和整数型,还有一个特殊值NaN

console.log( typeof  NaN ****)   // Number
var a = ' abc '
console.log( Number(a));

//NaN,表达式中存在不可转化的变量,返回了无效的结果,不是返回确切的值
//  NaN不等于本身,不是确切的值,代表一个范围

console.log(NaN == NaN) ;  // false  // 因为NaN不是一个确切的值
console.log(NaN I== NaN);  // true 

8、js 中判断数组的方法


//  通过object.prototype.tostring.call () 做判断;
console.log(Object.prototype.toString.call ( [ ] ) )  //  是字符串 [Object Array ] console.log(Object.prototype.toString.call ( [ ] ). slice(8, -1) )  //  Array console.log(Object.prototype.toString.call ( [ ] ). slice(8, -1) === 'Array' )  //true

// 通过原型链 做判断
// 对象的隐式原型等于构造函数的显式原型
console.log([._proto__a === Array.prototype);  

// 通过ES6的 Array.isArray() 做判断
console.log(Array.isArray());

// 通过 instanceof 做判断
console.log( [] instanceof Array);

//  通过Array.prototype.isPrototypeOf 做判断  判断Array是否在传入内容的的原型链上
console.log(Array.prototype .isPrototypeof( [] );

9、js 中操作符什么时候用于字符串的拼接 如果+操作符其中一个操作数是字符巾(或者通过ToPrimitive操作之后最终得到的字符串),则执行字符串的拼接,否则执行数字加法

var a={nane :”张三"》;     //  [object ojbect]
// a.valueof()
// a.tostring()
var b= { age:18 };         // [object ojbect]

// b.valueof()
// b.tostring()

var c = 1 ;
console.log( a+c );        //  [object ojbect] 1
console.log( a+b );        // [object ojbect][object ojbect]
console.log(1+1+'23');     // 2+'23'  ===> '223'
console.log(1+'23'+4+5);   // '123' +4+5  ===> '1234' +5 ===>'12345'

10、js 中Object.is () 与比较运算符 === 和 == 的区别

js中object.is() 与 比较操作符 “===“(严格相等运算符) 和”==" (相等运算符) 的区别

  1. 双等号(==): 如果两边的类型不一致,进行强制类型转换,然后再去进行比较

console.log(1==true);    //  -->1==1 --> true   true被转换为 number 1
console.log(1=='1');       // --> 1==1 --> true
  1. 三等号(===): 如果两边的类型不一致,不会进行强制类型转换,直接返回false,等型等值
console.log(1=== true);   // false
console.log(1==='1') ;       //  false 
console.log(NaN === NaN) ;  // false    实际希望为 true
console.log(+0 === -0) ;     //  true         实际希望为 false

不够严谨,使用es6新增 Object.is () 解决 3. Object.is(): 用来判断两个值是否严格相等,处理一些特殊的情况,-0和+9不再相等,两个NaN是相等的


console.log( Object.is(NaN,NaN) );    //  true
console.log( Object.is(+0,-0 ) ) ;        // false

11、js中如何进行隐式类型转换(主要发生在运算符之间)

ToPrimitive方法 : 这是Js中每个值隐含的自带的方法,用来将值(无论是基本类型值还是对象)转换为基本类型值 , 如果值为基本类型 , 则直接返回值本身 : 如果值为对象,其看起来大概是这样: ToPrimitive( obj , type ) obj --> 需要转换的对象 type --> 期望的结果类型 type的值可以为number或者string,默认情况下为number 1、当type为number时规则如下: (1) 调用obj的valueof方法,如果为原始值,则返回,否则下一步 (2) 调用obj的toString方法,如果为原始值,则返回,否则下一步 (3) 指出TypeError异m 2、当type为string时规则如下: (1) 调用obj的tostring方法,如果为原始值,则返回,否则下一步 (2) 调用obj的valueof方法,如果为原始值,则返回,否则下一步 (3) 抛出TypeError异常


var objToNumber = function (value) {
    return Number(value.valueOf().tostring())
}
console.log(objToNumber(0)=a= 0);   //   -->  0
console.log(objToNumber(0)-sE NaN);//-->NaN
 
// +操作符的两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串:其他情况下两边的变量都会被转换为数字。
 
// console.log(1 +"23" );     // 123
// console.log(1 + false);    // 1
// console.log('1' + false);  // 1false
// console.log(true + false); // 1
 
// - 、*、/ 操作运算符会转换为数字
 
// console.log(25 - "23"");   // 2
// console.log(1 * false);    // 0
// console.log(1 / 'aa');     // NaN
 
// 对于 == 操作符来说
 
// console.log(3 == true);    // false
// console.log('0' == false); // true
// console.log('0' == e);     // true
 
//对于< 和 > 比较符,(字母按照字母的排列顺序进行比较)
 
// console.log('c' > 'b');   // true
// console.log('de' > 'fg'); // false
 
//其他情况下,转换为数字再比较
 
// console.log( '12'< 13);   // true
// console.log(false < -1);  // false  0 > -1
 
//对象
 
// var a= {}   // 空对象
// console.log( a > 2);   // false
/*
 转换过程
console.log(a.valueof();           // {}
console.log(a.toString());         // [object Object ]
console.log(Number(a.tostring())); // NaN

12、 js中的深拷贝和浅拷贝的区别

1、 JS中 深拷贝 和 浅拷贝 的区别 主要在于复制出来的新对象和原来的对象是否会互相影响,改一个,另一个也会变 2、 浅拷贝 : 只是指向被复制的内存地址,如果原地址发生改变,那么浅拷贝出来的对象也会改变 新旧对象共享内存,修改其中一个,另一个也会受到影响 3、 深拷贝 : 在内存中开辟一块新的地址用于存放复制的对象 新旧对象不会共享内存,修改其中的一个不会影响另一个 4、 浅拷贝: 通过 = 直接赋值

var obj = { name:"张三", age:18 }
 
var obj1 = obj;
 
console.log(obj1);  // { name:张三", age: 18}
cbj1.age = 20;
console.log(obj);   // {name :张三", age: 20}
consolc.log(cbj1);  // {name: "涨三", age: 20}
 
// 浅拷贝常见的方法  Object.assign() 方法
 
var obj = {name:"张三",age:18};
var obj1 = Object.assign(obj)
obj1.age = 20;
console.log(obj);   // {name: "涨三", age: 20}
console.log(obj1);  // {name: "涨三", age: 20}

5、 深拷贝: (1)、通过JSON 对象实现深拷贝 JSON.stringify : 将js的值(对象或者数组)转为一个SON字符电 JSON.parse : 用来解析sON字符串,转换为0bject类型

var obj = {name:"张三" , age:18);
var obj1 = JSON.parse(soN.stringify(obj));
 
obj1.age = 20;
console.log(obj);      // {name: "涨三", age: 18}
console.log(obj1);    // {name: "涨三", age: 20}

(2)、使用扩展运算符实现深拷贝

var obj = {name:"张三" , age:18);
var obj1 = {...obj,age:20}
 
console.log(obj);      // {name: "涨三", age: 18}
console.log(obj1);    // {name: "涨三", age: 20}

13、js中与和或操作符的返回值

js中 && (与) 和 ||(或) 操作符的返回值 首先对第一个操作数进行条件判断,如果不是布尔值,就先强制转换为布尔类型,然后进行条件判断 || (或)

console.log(1 || 2);  //-->1(真),如果第一个操作数为真,返回第一个操作数的值
console.log(0 || 2); //-->2(真),如果第一个操作数为假,返回第二个操作数的值

&&(与)

console.log(1 && 0); //-->0(假),如果第一个操作数为真,返回第二个操作数的值
console.log(0 && 2);  //-->0(假),如果第一个操作数为假,返回第一个操作数的值

|| 和 && 不是返回条件判断的结果返回它们其中一个操作数的值

14、 js 中 == 操作符的强制类型转换规则

首先判断两者的类型是否相同,如果不相同会进行类型转换,相同的话就比较大小1/转换情况: (1)、字符串和数字之间的相等比较,将字符串转换为数字之后再进行比较大小 1== '1' --> 1 == 1 -->true (2)、其他类型和布尔类型之间的相等比较,先将布尔值转换为数字后,再应用其他规则进行比较 true == '1' --> 1=='1' --> 1==1 --> true (3)、nul1和undefined之间的相等比较,结果为真,其他值和它们进行比较都返回假值 (4)、对象和非对象之间的相等比较,会将对象先转为基木数据类型再进行判断 ‘1’=={} --> '1' == "[object object]" (5)、如果两个操作值都是对象,则比较它们是不是指向同一个对象,如果两个操作数都指向同一个对象,则相等操作符返回true ,否则返回false var a={} ; var b=a; var c={}; console.log(a==b); // true console.log(a==c); // false

15、js中 isNaN 与 Number.isNaN() 的区别

isNaN : 为了判断一个计算结果或者变量的值是否为NaN isNaN(value) : value表示检测的值 isNaN 的判断过程 : 首先进行类型检测,如果传入的参数不是数值类型,第二步将传入的参数转为数值类型,然后再进行是否为NaN的判断

Number("")    // 0
Number(null)  // 0
Number(true)  // 1
Number(false) // 0
Number(undefined)  // NaN
Numben('aa') // NaN
 
-----------isNaN()--------------- 
 
//isNaN()
console.log(isNaN(NaN));      // true
console.log(isNaN(true));     // false 
console.log(isNaN('aaa'));     // true
console.1og(isNaN(null));      // false
console.log(isNaN(''));        // false
consoie.1og(isNaN(undefined)); // true
 
--------Number.isNaN()---------------'
// Number.isNaN() ES6出来的Number对象的扩展的方法
// Number.isNaN(value): value表示检测的值
// Number.isNaN的判断的过程:首先进行类型检测,如果传入的参数不是数值类型,直接返回felse ,如果判断是数值类型,然后isNaN()的方式进行判断
console.log(Nunber.isNaN(true));     //false
console.log(Number.isNaN(""));       //false
console.log(Number.isNaN(nul1));     //false
console.log(Number.isNaN(NaN));      //true
console.log(Number.isNaN(123));      //false
console.log(Nunber.isNaN( 'aaa'));   //false
console.1og(Number.isNaN(undefined)); //false

16、es6中的 const 定义的 对象的属性 可以修改吗?

可以修动 const 是保证 变量指向内存地址 不能改动,变量的值 可以改动


const obj = (name:”张三",age:18); 
obj.name= “ 李四 ”   //可以修改 obj={}        
console.log(obj);   // 报错  

17、ES6中 let、 const 和 var 之问的用法以及区别

var: 1、使用var声明的变量既是顶级交量(顶层对象(window对象)的属性)也是全局变量 2、使用var声明的变量存在变量提升的情况 3、使用var可以对一个变量进行多次声明,后面的声明会覆盖前面的变量声明 4、在函数中再次使用var声明这个变量的时候,这个变量就是局部的,如果不是用var,那就全局的


// 使用var声明的变量既是顶级交量(项层对象(window对象)的属性)也是全局变量
 var a=10;
 console.log(window.a); // 10
 
// 使用var声明的变量存在变量提升(提升变量声明)的情况
 console.log(b); // undefined
 var b = 10;  //声明并且赋值
 
 // 运行过程
 // var b; 
 // console.log(b); // undefined
 // b=10;
 
// 使用var可以对一个变量进行多次声明,后面的声明会覆盖前面的变量声明
 var c= 10;
 var c= 40;
 console.log(c); // 40 
 
//在函数中再次使用var声明这个变量的时候,这个变量就是局部的,如果不是用var,那就全局的
var d=10;
function fun1((){
 var d=20;
}
fun1()
console.log(d); //10

let: 1、 let 所声明交量只在let命令所在的代码块中生效let不存在变量提升 2、 let 不允许在相同的作用域下重复声明

//  let所声明变量只在let命令所在的代码块中生效/块级作用域
    let num=18
       console.1og(num);  // 18
     }
//  let不存在交量提升
 
    let num1;
    console.log(num1);  // 报错
 
//  let不允许在相同的作用域下重复声明
 
     num1 = 20   // 报错

const : const声明一个只读的常量,一旦声明,常量的值就不能改变const一旦声明,就必须赋值 除了以上的其他的都和let一样的

// const声明一个只读的常量。一且声明,常量的值就不能改变
 
    const sum =103;
    sum = 200;
    console.log(sum);   // 报错,不能再次赋值
 
 
//  const一旦声明,就必须赋值
 
    const total;
    console.log(total);   // 报错,缺少初始值



区别:
交量提升:
var声明的变量存在变量提升,let和lconst不存在变量提升
块级作用域:
var不存在块级作用域,letconst存在块级作用域,只在所在代玛块生效
重复声明:
var允许重复声明,letconst不允许在同一个作用域重复声明
修改声明的变量:
varlet可以改变声明的变量,const,不可以,一旦声明,必须赋值,并且常经的值不能改变

18、js中如何的断一个对象是空对象


//  使用JSON自带的.stringify方法来判断
 
     var obj={
         name:"张三"
      }
      console.log(JSON.stringify(obj));     // {}  是一个字符串
 
      if (JSON.stringify(obj) === “0") {
         console.log(“是一个空对象"");
      }
//  使用object.keys()来判断//key:键名
//  value:键值
    var obj1= { name:"张三", age:18 };
    console.log(Object.keys(obj1));    //    返回一个数组
    if ( Object.keys(obj1).length==0 ) {
        console.1og("是一个空对象);
    }

19、 ES6中new一个箭头函效会怎么样 --->报错

new关键字的执行过程: new构造函效会内存中创建一个空对象this就会指向刚才创建的这个空对象 执行构造函数中代码,给空对象添加属性和方法返回这个新的对象(所以构造函数中不需要return)


/箭头函数
//箭头函数内的this是静态的,指向定义时所在的对象,而不是调用时,this指向不可以改变的var id=10;
  var obj=i
  id:100,
  a:function(){
    // 谁调用这个函数,this就指向谁
    console.log(this.id)  
  },
 
  b:()=>{
    // this是静态的,指向定义时所在的对象(window对象),所以箭头函数不可以当做构造函数来使用
    console.log(this.id);
  }
)
obj.a()  // 100
 
obj.b()  //10
console.log(new obj.a());  undefined
console.log(new obj.b());  a{}

20、js 中对原型的理解

构造函数: function Person(){ } prototype(原型)属性,默认对应着一个空对象(没有我们制定的方法和属性),这个空对象就是我们所说的原型对象,每一个prototype都是不相等的 console.log(Person.prototype)

显式原型和隐式原型: 每一个函数都有一个prototype属性,就是显式原型 每一个实例对象都有一个_proto_,就是隐式原型 实例对象的隐式原型 等于 对应的构造函数的 显示原型的值

构造函数
function Fun( ){  // 内部语句:Fun(this). prototype={}

}
console.log(Fun.prototype);
var fun=new Fun() //  内部语句:fun(this).proto_=Fun. prototype console.log(fun.proto);
console.log(Fun.prototype===fun.proto_);  // true

//  总结:
//  函数的prototype属性,在定义函数是自动添加的,默认值是一个空对象
//  对象的_proto__属性,创建对象的时自动添加的,默认值是构造函数的prototype属性

编辑切换为居中

添加图片注释,不超过 140 字(可选)

21、js中对原型链的理解


function Fun{     // Fun(this).prototype={}
     this.test1=function(){
          console.log( 'test1()");
      }
 }
Fun.prototype.test2=function(){
      console.log( 'test2()');
}
console.log(Fun.prototype);
console.log( object.prototype.__proto__);
var fun=new Fun();    //  fun(this)._proto__=Fun. prototype
 
fun.test1();     // test1
fun.test2();    //  test2
console.log(fun.tostring())   //  [ object Object ]
 
fun.test3();    // 报错

编辑切换为居中

添加图片注释,不超过 140 字(可选)

22、 js 对原型的修改和重写

// JS中对原型的修改和重写
function Person(name){
  this.name=name
}
//修改原型
Person.prototype.getName = function(){
   console.log(this.name);
}
var p=new Person("张三");
 
// 修改原型不会影响构造函数的显式原型 等于 实例对象的隐式原型
 
console.log(p._proto_=== Person.prototype);//true
console.log(p.___proto__=== p.constructor.prototype);//true
 
 
//重写原型  会有影响  p.constructor 的指向改变了
 
Person. prototype={
  getName:function(){
    console.log(this.name);
  }
}
// 直接给Person的原型对象用对象进行赋值时,p的构造函数指向根构造函数
objectvar p=new Person("张三");  // p(this)._proto__=Person.prototype
console.log(p._proto__===Person.prototype); //true
console.log(p.constructor); // object 指向改变了
console.log(p._proto__===p.constructor.prototype); //false
 
// 通过constructor 让p的指向恢复
 
p.constructor=Person;
 
console.log(p._proto__===p.constructor.prototype); //true

23、for ...of 和 for ... in 的区别

  • ES6中 for. . .of 和 for . . .in (性能差)的区别 for. . .of遍历获取对象的键值,for. . .in获取对象的键名 for. . .of只遍历当前对象, for. . .in会遍历对象整个原型链
  • 对于数组的遍历 for . ..in返回数组中所有可枚举的属性 for ..of返回数组的下标对应的属性值

for . ..in,主要是为了遍历对象而产生,不适用于遍历数组 , for ..of,我环可以用来遍历数组,类数组对象,字符串,set map .....


function Person(name,age,sex){
  this.name=name
  this.age=age
  this.sex=sex
}
Person.prototype.height=188
var p=new Person(“张三"",18,男")
P[Symbol.iterator]=function(O){
  var keys = object.keys(this);
  var index = 0;
  return {
    next({
      if(index<keys.length){
         return {value:p[keys[index++]],done:false}
      }else{
         return {value:undefined,done:true}}
    }
  }
}
for(let value of p){
  console.1og(value);   // 张三 18 男
}
------------------------------
for(let key in p){
  console.log(key);     // name age sex height
}
-------------------------
var arr=[1,2,3,4,5]
console.log(arr);
 
for(let i in arr)
  console.log(i);
}
 
for(let i of arr){
   console.log(i);
}
 

编辑

添加图片注释,不超过 140 字(可选)

24、js 中如何判断 一个属性 是属于实例对象 还是继承与构造函数

JS中如何判断一个属性是属于实例对象还是继承于构造函数 通过hasOwnProperty() // 检测一个属性是否属于自身对象,还是继承于原型链上的

function Person(name,age){
   this.name=name;
   this.age=age;
}
Person.prototype.sex = "男" ;

var p=new Person ("张三",18);

p.phone=12345;
p.height=188;

console.log(p);
console.log(p.hasOwnProperty("phone")); //true

console.log(p.hasOwnProperty ( "sex")); //true

for (let i in p){
  if (p.hasOwnProperty(i)){   //   hasOwnProperty() 筛选掉原型链上的属性
      console.log(p[i]);
  }
}

编辑

添加图片注释,不超过 140 字(可选)

25、js 中bind 和call 、apply 的作用以及他们的区别

作用: 改变函数运行时 this 的指向

var uname = " 张三 " 
var obj={
uname : "李四" ,
   say: function() {
console.log(this.uname);
}
}
obj.say()  //李四
setTimeout(obj.say,0)  // 张三
setTimeout(obj.say.bind(obj),0)  // 李四
//  setTimeout   里面函数里面的this 指向 window  的 this

区别 :

aplly: 两个参数,第一个是this指向,第二个是函数接收的参数,以数组的形式传入


function fun(...argus){
console.log(this);
   console.log(...argus);
}
var person={
myname : "王五"
}
fun.apply(person,[1,2,3,4]);   //  传入的参数必须是一个数组fun(1,2,3,4)

//  如果第一个参数 null 或者 undefined ,this 默认指向 window
fun.apply(nul1,[1,2])
fun.apply(undefined,[1,2])

编辑

添加图片注释,不超过 140 字(可选)

call : 两个参数,第一个是this指向,第二个是参数列表 fun.call(person,1,2,3,4) call和aplly改变this指向原函数立即执行,临时改变this指向一次 fun(1,2,3,4) bind:两个参数,第一个是this指向,第二个是参数列表 改变this指向不会立即执行,返回一个永久改变this指向的函数 var bindFun= fun.bind(person) bindFun(1,2,3,4) bindFun() 总结:三者第一个都是this指向,第二个是函数接收的参数

26、es6 对 promise 的理解以及他的实例方法

是异步编程的一种解决方案 三种状态: pending(进行中),fulfi1led(已成功),rejected(已失败) 特点: 状态不受外界的影响,只有异步操作的结果,决定当前是哪一种状态 一旦状态改变就不会再变(pending-->fufilled , pending-->rejected) 用法:Promise是一个构造函数,用来生成Promise实例 (1)、Promise构造函数接收一个函数作为参数,这个函数有两个参数

const p=new Promise(function(resolve,reject) {
        //resolve函数:将Promise对象的状态从未完成变成成功,在异步操作成功的时候调用,              
       resolve()  //  返回异步操作的结果,作为参数传递出去
       //reject函数:将Promise对象的状态从未完成变成失败,在异步操作失败的时候调用,           
       reject()  // 返回异步操作的结果,作为参数传递出去
})

(2)、 Promise实例方法


const p = new Promise( function (resolve,reject) {
      setTimeout(O=>{
            const time=new Date().getTime(

             if( time%2 == 0){
                  resolve('成功的数据。 time = '+time)

             }else{
                  reject(·失败的数据,time = '+time)
             }

        },1000)
})
p.then((value)=>{     //  resolved(己成功)的状态
      console.log( 成功的' + value);
},(reason)=>{  //  rejected(已失败)的状态
      console.log( 失败的' + reason);
}).catch((value) => {
      console.log(value)

}).finally(() => {
       console.log('最后的结果')

})

then():当实例状态发生改变的时候的回调函数,放回的是一个新的Promise 实例,也就是Promise 可以链式书写的原因。 catch() :用于指定发生错误的回调函数,一般来说通过 catch 替代 then 中第二个参数 finally() :用来指定不管Promise对象状态最后如何,都会执行的操作



setTimeout(() => {   //  例如多个嵌套  //  多个串联嵌套的异步操作形成的回调地狱
    console.log(111);
    setTimeout(() => {
        console.log(222);
        setTimeout(() => {
           console.log(333);
        },3000)
    },2000)
},1000)


----------------------------------------------------

function fun(ms, val,nextval) {
     return new Promise((resolve, reject) => {
           setTimeout(() => {
                resolve(222)
                console.log(111);

           },ms)
      })
}
fun(1000).then((value) => {
       return new Promise((resolve, reject) => {
             setTimeout(() => {
                  console.log(value);

                  resolve(333)
             },2000);

        })
}).then ((value) => {
       return new Promise((resolve, reject) => {
           setTimeout(() => {
                console.1og(value);
           },3000)
      })

})

27、什么是回调地狱(多个串联的异步操作)以及如何使用Promise解决

通过 then 链式调用 歌单--->歌单列表--->歌曲的信息 需求:一秒钟之后输出1,然后两秒钟之后输出2,然后三秒之后输出3



setTimeout(() =>{
        console.log(1);

        setTimeout(0 =>{
              console.log(2);

              setTimeout(() =>{
                    console.log(3);

              }, 3000)
       }, 2000)

},1000)

------------------使用promise 实现------------------------

function getData() {
      return new Promise((resolve, reject) => {
           setTimeout(() => {
               console.log(1);

               resolve(2)
           },1000)
       })
}
getData() . then ((value)=>{
        return new Promise((resolve, reject) =>{
                setTimeout(() => {
                        console.log(value);

                         resolve(3)
                },2000)
         })

}).then((value)=>{
        return new Promise((resolve,reject) => {
                setTimeout(() =>{
                        console.log(value);

                }, 3000)
        })
})

添加图片注释,不超过 140 字(可选)

28、ES6中对Promise.all的理解以及应用场景

ES6中对Promise.all的理解以及应用场景

let p1=new Promise((resolve,reject)=>{
        resolve("成功81")
)
let p2=new Promise((resolve,reject)=>i
        resolve("成功e2")
)
let p3=new Promise((resolve,reject)=>{
        resolve("成功83")
)
//  参数可以不是数组,但是必须是iterator接口

let pAll=Promise.al1([p1,p2,p3])

console.log(pAll)

// pAll的状态,由p1,p2,p3来决定,只有当这三个都为成功,pAll才会为成功,
// 但是有一个失败,那么就是失败,这个时候第一个失败的实例的返回值,会传递给pA11的回调函数//如果作为参数的实例,自己定义了catch方法,那么它一旦rejected,不会触pAll的catch方法

pAl1.then((value)=>{
        console.log(value);

}).catch((reason)=>{
        console.log(reason)

})
// 多个请求结果合并在一起

function getBannerList(){
     return new Promise((resolve,reject)=>{
          setTimeout(O=>{
              resolve( 轮播图的数据")

          },1000)
     })
}

function getMusicList(() {
     return new Promise((resolve,reject)=>{
        setTimeout(() => {
             resolve( "歌曲列表的数据')

         } ,2000)
   })
}
function getCateList(){
    return new Promise((resolve,reject)=>i
        setTimeout(() => {
             resolve(歌单分类的数据')

        },3000)

}

function initLoad() {
        let All= Promise.al1([getBannerList(),getMusicList(),getcateList(])

        console.log(All);
        All.then((value) => {
                console.log(value);”
        }
initLoad()

编辑

添加图片注释,不超过 140 字(可选)

编辑

添加图片注释,不超过 140 字(可选)

29、ES6中Promise.race的用法以及使用场景

将多个Promise实例包装成一个新的Promise实例

let p1 = new Promise((resolve,reject) =>{
        setTimeout(() =>{
            resolve(p1成功)

        }, 2000)
})
let p2=new Promise((resolve,reject)=>{
     setTimeout(()=>{
         resolve('p2成功‘)

   },1000)
})
//调用
const prace=Promise.race([p1,P2];

console.log(prace);


//Promise.race区别于Promise.all:只要实例中有一个先改变状态,就会把这个实例的多数的返回值传给prace的回调函的/使用场景:请求超时提示


function request(){
        return new Promise((resolve,reject)=>{
                setTimeout(() =>{
                        resolve("请求成功")

                },4000)

        })

}
function timeout() {
      return new Promise((resolve,reject)=>{
           setTimeout(()=>{
                reject(网络不佳,请求超时")

           },3000)
      })

}

Promise.race( [request(),timeout()] ).then((value)=>{
        console.1og(value);
}).catch((reason) => {
console.log(reason);

})

30、 ES6中使用Promise封装ajax

http://localhost:3808/personalized21imit-10


function getsON(ur1){
 
  return new Promise((resolve, reject) =>{
    //创建一个实例对象
    let xhr = new XMALHttpRequest();
    //新建一个http请求
    xhr.open( 'GET", url, true);
    //发送http请求
    xhr.send(null)
    //设置状态的监听函数
    xhr.onreadystatechange = function(){
        if(xhr.readyState !== 4) return//表示请求完成
        //当请求成功或者失败,需要改变promise实例的状态
        if (xhr.status >=200 && xhr.status < 300){
            resolve(xhr.responseText)/请求结果
        }else{
            reject(new Error((xhr. statusText))
        }
    }
    //设置错误的监听函资
    xhr.onerror = function (){
        reject(new Error(xhr.statusText))
    }
    //设置响应数据的类型
    // xhr.responseType - 'json"”
  })
}
    getJSON( " http://localhost:3000/personalized?1imit-10').then((value)=> {                              
        console.1og(as0w. parse(value));
    }).catch((reason) =>{
        console.log(reason);
})

31、Js中ajax(Async Javascript and XML)的原理是什么?如何实现

原理: 通过XNLHttpRequest对象来向服务器发送异步请求,从服务器获取数据,然后用js来操作DOM去更新页面 实现过程: -创建Ajax的核心对象 XMLHttpRequest对象 new XMLHttpRequest(()实例化对象 -通过 XMLHttpRequest对象的 open()方法与服务端建立连接 new XMLHttpRequest().open(method:表示请求方式,url:服务器的地址) -构建请求所需的数据内容,并通过XMLHttpRequest 对象的 send()方法发送给服务器端。 new XMLHttpRequest(.send(body:发送的数据) 如果使用get 请求发送数据,send()参数设置为null -通过 XNLHttpRequest对象提供的 onreadystatechange事件监听服务器端的通信状态 new XNLHttpRequest().onreadystatechange主要监听的属性是实例化对象中readyState(五个状态): 0:open()未调用, 1: send()未调用, 2:send()已经调用,响应头和响应状态已经返回, 3:响应体正在下载,responseText(接收服务端响应的结果)获取到部分的数据, 4: 整个请求过程已经完毕 只要readystate属性值发生了改变,onreadystatechange被触发 -接受并处理服务端向客户端响应的数据结果 -将处理结果更新到HTML页面中


const xhr =new XMLHttpRequest(){
    xhr.open("GET",'http:/ /localhost: 30e0/ personalized?limit=10')
    xhr.send(nul1)
    xhr.onreadystatechange=function(){
        if(xhr.readystate === 4){
            if(xhr.status>=200 && xhr.status<300){
                console.1og(xhr.responseText);
            }
            let obj=JSON.parse(xhr.responseText)
            console.log(obj);
            obj.result.forEach(item =>{
                var div=document.createElement('div');
                div.innerHTML=item.name
                document.querySelector( 'body' ).appendchild(div)
            })
        }else if(xhr.status>=400){
            console.1og(“错误信息"+xhr.status);
        }
    }
}

32、Js中localstorage和sessionStorage的区别

Js中localStorage和lsessionStorage的区别 localstorage:永久存储在本地,适合保存在本地的数据 sessionStorage:会话级的存储,敏感账号一次性登录 相同点: 都是保存在浏览器端 不会把数据自动的发送给服务器,仅在本地保存 只能存储字符串,可以将对象JSON.stringfy()编码之后进行存储 不同点: 存储大小限制不同:sessionStorage存储的大小为5M, 1ocalstorage存储大小为20M 数据有效期不同: localStorage: 始终有效,窗口关闭或者浏览器关闭,一直保存,持久保存数据sessionStorage: 仅在当前浏览器窗机关闭前有效,会话级存储 作用域不同: sessionStorage: 在不同的浏览器窗口否会进行共享,只有同一个页面中 localStorage: 在所有的同源的窗口下可以共享的

33 、js中的事件流

​事件流: 从页面中接收事件的顺序

事件流分为三个阶段:捕获阶段、当前目标阶段、冒泡阶段

addEventListenter(事件,回调函数,布尔值(false冒泡,true捕获)默认为false)//事件捕获:不太具体的节点先接收到事件,而最具体的节点最后接收事件

varone=document.querySelector( '.one ' );
one.addEventListener( " click " ,function({ alert("我是子元素");
},true);

var-box=document.queryselector(".box");
box.addEventListener( ' click " ,function({.-  alert("我是父元素");
},true);

// 先弹出父元素,在弹子元素

事件冒泡:最具体的节点先接收事件,不太具体的节点最后接收到事件

var one=document.querySelector( .one ');
one.addEventListener( 'click" ,function(){
alert("我是子元素");
});

var box=document.querySelector("box");box.addEventListener('clik ' ,function({
alert("我是父元素");
);

// 先弹出子元素,在弹父元素

编辑

添加图片注释,不超过 140 字(可选)

编辑

添加图片注释,不超过 140 字(可选)

34、js如何阻止事件冒泡和默认行为

JS中如何阻止事件冒泡和默认行为

事件对象: event对象,当成形参来看,包含所有与事件相关的信息,比如触发事件的元素,事件的类型...

var box=document.queryselector( " .box ')
 box.addEventListener( "click" ,function(e){
   console.log(e);
 })
 
//阻止默认行为
 var a=document.querySelector('a')
 a.addEventListener( 'click " ,function(e){
    e.preventDefault()
    //兼容性
    // ie 678
    e.returnvalue=false1/ })
    a.onclick=function(e){
    //没有兼容性问题,只限于传统方式
    return false
}
//阻止事件冒泡
var one =document.querySelector( '.one ');
one.addEventListener( 'click ' ,function(e){
    console.log(e);
    alert( 我是子元素:)
    //e.stopPropagation()
    //ie 678
    e.cancelBubble=true
 )}

35、js实现函数的防抖

1、 防抖的场景:登录,发验证码,等按钮用户点击太快,以及发送多次请求

2、 调整浏览器窗口大小的时候,resize次数过于频繁,造成计算过多,一次计算到位。

3、 搜索框搜索输入

//防抖和节流:限制函数执行的次数Js中实现函数的防抖
//通过setTimeout的方式,在一定的时间间隔内,将多次触发变成一次触发
var ipt = document.querySelector( '#ipt ');
var btn = document.querySelector( " #btn ");
// btn .addEventListener( 'click " ,getvalue);
btn.addEventListener( " click ' , debounce(getvalue,2000));

function getvalue(e){
var val = ipt.value;
  console.log(val);
   console.log(this);
   console.log(e)
}

function debounce(fn, time) {
    var t = null1/定义最开始的定时器
    return function (e){
    console.log(e)
    console.log(arhuments)
    console.log(this)
    var that=this
        if (t){//判断定时器是否生成,如果生成了,清除上一个定时器
            clearTimeout(t)
}
var firstclick =!t
/如果是第一次点击就立即执行
    if(firstClick)(
        // fn(e)
        fn.apply(this,arguments)
    }
    t = setTimeout(function (){
        t=null
    ), time)}
}

36、js实现函数的节流

1、节流的应用场景: scroll:每隔一秒计算一次位置信息

2、搜索框实时搜索,并且发送请求,展示下拉列表,每隔两秒发送一次请求

J5中实现由数的节流
防抖和节流:限制函数执行的次数
节流:减少一段时间的触发频丰(时间戳),控制事件发生的频率,控制在2s发生一次
var ipt = document.queryselector( "#ipt );
var btn = document querySelector( " #btn);
// btn.addEventListener('click", getvalue);
btn.addEventListener('click",throttle(getvalue,2000))

function getvalue({
   var val = ipt.value;
   console.log(val);
}
function throttle(fn,time){
var begin=e;//设置时间的初始值(上一次点击的时间)
return function(){
//拿到当前的时间戳
 var date=new Date().getTime()
 var that=this
 console.log(date-begin);
 if(date-begin>time){
  fn.apply(that,arguments)
  begin=date
 )
}
}

37、对箭头函数的理解

ES6对箭头函数)=>0)的理解,在书写代码的时候确定this的指向基木使用

ES6之前,谁调用了函数,this.就指向谁
let fun=function(a,b){
   console.log(a+b)
}
es6之后,使用箭头函数
let fun1=(a,b){
    console.log(a+b)
 }
 fun(1,3)
 fun1(1,3)
 
 注意点:
// 箭头函数内的this是静态的,总是指向定义时所在的对象,而不是调用时。并且this指向是不可以改变的
var name=张三";
var obj-{
   name:李四”
}

function fun(){
   console.log(this.name);
 }
let fun1=()=>{
   console.log(this.name);
 }
fun()
fn1()

fun.call(obj)
fun1.call(obj)
this指向是不可以改变的
this始终指向函数声明是所在作用域下的this的值

---------------------------------------------------

var name=张三";
var obj-{
   name:李四”
}

function fun(){
    var name ='王五'
   console.log(this.name);
 }
 function fn(){ //fn的this指向window
   var name='赵六'
 
   let fun1=()=>{
     console.log(this.name);
   }
   fun1()
 }
fun()  //张三
fn1()  // 张三
fn.call(obj)  //李四  改变了指向 fn的指向obj

1this始终指向函数声明时所在作用域下的this的值。
2、箭头函数不能当做构造函数,也就是不可以用new命令,否则报错。
let Person=(name, age)=>{
this.name=name
this.age=age
let child=new Person("张三",18)  // 报错

3、箭头函数不存在arguments对象,即不能使用伪数组去接收参数,可以使用rest参数代替。

function getArgOi
console.log(argu-ents);
)
getArg(1,2,3,4,5)
let funArg=()=>{
console.log(arguments);
}
funArg(1,2,3,4,5)


正确的: 可以使用rest参数代替
换成
let funArg=(...b)=>{
console.log(arguments);
}

38、Js中1ocalstorage和IsessionStorage的区别

Js中localstorage和 sessionStorage的区别

localstorage:永久存储在本地,适合长期保存在本地的数据

sessionstorage:会话级的存储,敏感账号一次性登录

相同点:

都是保存在浏览器端不会把数据自动的发送给服务器,仅在本地保存

只能存储字符串,可以将对象JsON.stringfy(()编码之后进行存储

不同点:

存储大小限制不同:sessionStorage存储的大小为5M, localStorage存储大小为2eM

数据有效期不同: localStorage:始终有效,窗口关闭或者浏览器关闭,一直保存,持久保存数据

sessionStorage:仅在当前浏览器窗机关闭前有效,会话级存储

localStorage.setItem('b',456)

作用域不同:

sessionstorage:在不同的浏览器窗口不会进行共享,只有同一个页面中

localstorage:在所有的同源的窗口下可以共享的

sessionStorage.setItem('a',123)

39、js对事件代理的理解以及有用场景

<ul id="list">
    <li>item1</li>
    <li>item2</1i>
    <li>item3</li>
    <li>item4</li>
</ul>

<script>
1、jS中对事件代理的理解以及应用场景  事件冒泡
2、事件代理:把一个元素响应事件的函数委托到另一个元素上,也叫事件委托
3、事件流:捕获阶段-->目标阶段-->目泡阶段(事件委托)

 let lis=document.querySelectorAll(""li");
for(let i=0;i<lis.length;i++){
lis[i].onclick=function(e){
  //e.target返回触发事件的对象
  console.log(e.target.innerHTML);
 }
]
let oul=document.queryselector("#list");
oul.onclick=function(e){
   console.log(e.target.innerHTML);
}
// 只要操作一次DoM,从而提高了程序的性能

</script>

let obtn=document.querySelector("#btn");
obtn.onclick=function(e){
  num++;
  let oli=document.createElement("li");
  oli.innerHTML=`item${num}
  oul.appendchild(oli)
)

40、jS中对 作用域 和 作用域链 的理解(查找变量)

jS中对作用域链的理解(查找变量)

作用域:变量和函数生效的区域

function fun((){
let a=10;
)
fun();
console.log(a);

全局作用域:任何不在函数中或者大括号中声明的变量,都是在全局作用域下全局作用域下的声明的变量可以在程序中任何位置访问

var a=10
function fun0ilconsole.log(a);}
fun()

函数作用域:函数作用域中定义的变量,只能在函数内部访问,不能在函数外部访问

function fun2O{
var b=20
console.log(b);
}
fun20//2e
// console.log(b);//报错

块级作用域: let和lconst定义的变量在大括号外面不可以被访问到 let和const

{
let uname="张三”;
const age=18;
var sex="男"
console.log(uname,age,sex);
console.log(a)  // 作用域链就是比如在块级作用域下打印a,现在当前作用域找,找不到就去上级作用域找
}
/console.log(window);
console.log(sex);
console.log(uname,age);

作用域链:js使用一个变量,首先js引擎会在当前作用域下查找,如果没有找到,去上层作用域寻找,依次类推,直到找到变量或者到达全局作用域,如果没有找到,直接报错或者隐式声明

var sex=“男"
function person(){
    var name="张三”
    function student(){
        var age=18
        console.log(name);//张三
        console.log(sex);/1男
    }
    student()
    console.log(age);//报错
}
person()

41、js清空数组的方法

var arr=[1,2,3,4,5]
1、splice
第一个参数:规定添加或删除元素的位置
第二个参数:要删除元素的数量
//splice 会影响原数组
arr.splice(0,arr.length)
console.log(arr)  // []

// length:数组的长度
arr.length=0
console.log(arr) //[]

//赋值为[]
arr=[]
console.log(arr) // []

42、js如何实现继承

  • B继承A ,B(子类)-->A (父类) 徉承可以使子类具有父类的各种属性和方法
  • 汽车(类) 属性:颜色,轮胎,品牌
  • 轿车:后备箱
  • 货车:大货箱

实现方法:

1、原型链的继承

子类的实例对象使用的是同一个原型对象,内存共用

function Person(){
    this.nome="Person";
    this.arr=[1,2,3,4]
}
console.log (new Person()),
function Child({
    this.type="child”
}
child.prototype= new Person()
var c1= new Child()
var c2= new Child()
c1.arr.push(5)
console.log(c1);
console.log(c2);

2、构造函数的继承

不能继承原型属性上的方法和属性

function Person(){
    this.nome="Person";
    this.arr=[1,2,3,4]
}

function Child({
    Person.call(this)
    this.type="child”  // this指向 new Person()
}

3、组合继承(常用)

function Person(){
    this.name='Person'
    this.arr=[1,2,3,4,5]
}
Person.prototype.age=18
function Child(){
    Person.call(this)
    this.type = "child"
 }
Child.prototype = new Person();
// Child.prototype=new Person()
// Child.prototype.constructor=Child
var c1=new Child()
var c2=new Chi1d()

console.log(c1.constructor)
c1.arr.push(5)
console.log(c1);
console.log(c2);

43、js事件循环机制

js是单线程的 从上到下,同步,异步,微任务,宏任务

1、同步异步代码

setTimeOut在0的时候的实际表现是4ms,但只是表示定时器最低的响应是4ms 如果是10的时候就是10ms,不需要加4ms

2、微任务和宏任务

首先是同步任务,异步任务,异步任务里面有宏任务和为任务之分

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

  • 先同后异 先微后宏
  • promise:promise调用then之后的代码才是异步的
  • async await 是使用同步的方式实现异步

编辑

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑

添加图片注释,不超过 140 字(可选)

const p = function() {
  return new Promise((resolve, reject) =>{
    const p1 = new Promise((resolve, reject) =>{
      setTimeout(()=> {
        resolve(1)
      },0)
      //resolve{2)
    })
    p1.then((res) => {
      console.log(res);
    })
    console.log(3);
    resolve(4);
  })
}
p().then((res) =>{
    console.log( res);
})
console.log ('end');


3
end
4
1

为什么要引入微任务的概念,只有宏任务可以吗?

宏任务:先进先出的原则执行

浏览器中的事件循环具体的机制是什么?

完成一次宏任务后,再去清空微任务,继续执行下一个宏任务

在整体的一个宏任务执行完以后,会把他中途中碰到的微任务已经添加到队列里面的执行一遍,如果微任务队列里面又碰到了新添加的微任务会继续执行为人无,直到执行完毕。(event loop)在去执行下一个宏任务

44、事件的冒泡和捕获机制

1、概念

  • 捕获:自顶向下
  • 冒泡:自底向上

编辑

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

45、防抖和节流

1、基本概念

  • 防抖:
  • 节流:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

46、promise相关

promise是在创建之初,实例化的时候就执行的

promise.all 你知道有什么规范吗? 1、会接受一个数组,数组被编译成promise

  • 1、promise是异步编程的一种解决方案,可以替代传统的解决方案(回调函数和事件)
  • 2、对象的状态不受外界影响promise对象代表一个异步操作,有三种状态:pending(进行中),fufilled(已成功)、rejected(已失败),一但发生改变就只有一种状态:Pending -> Fulfilled Pending -> Rejected。 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。