2022前端面试经验题

1、让元素在页面上消失的方法:
  • 利用 opacity = 0 ,但它只是视觉上的隐藏,元素本身依旧占据位置并对网页的布局起作用;
  • 利用 visibility = hidden ,被隐藏的元素依旧占有空间
  • 利用 display = none , 被隐藏的元素完全不会占用空间,仿佛元素完全不存在
  • 利用 position , 把元素定位到可视区域外,不会影响到布局
  • 利用 transform:scale(0),将一个元素设置为缩放无限小,元素将不可见,但元素原来所在的位置将被保留
  • 利用 height = 0 ,将元素高度设置为0,并清除边框
  • 利用 overflow = hidden , hidden隐藏溢出的显示,scroll溢出的显示滚动条
2、CSS选择器及其优先级
  • 全局选择器 * (通配符选择器)

  • 标签选择器 div (元素选择器)

  • 类选择器 .classname

  • ID选择器 #app

  • 后代选择器 .nav ul li ,用空格隔开,从父级到子孙级的选择器

  • 相邻兄弟选择器 h1+p ,选择一个元素后的相邻兄弟元素

  • 普通兄弟选择器 h1~p ,选择一个元素后的所有兄弟元素

  • 子选择器 div>p , 选择div里面的所有p子元素,从父级到子级的选择器

  • 伪类选择器 :hover \ :link \ :active \ :visited

  • 属性选择器 [属性] 选择某个属性的元素,而不论属性值是什么,可以使用简单属性选择器,如[title] a[href = ‘xx’]具体属性

    !important > 行内样式 > ID选择器 >  类选择器 > 标签选择器 > 通配符选择器
    
3、CSS实现三角形
div {
  width: 0;
  height: 0;
  border: 40px solid;
  border-color: tansparent transparent red;
}
4、 冒泡排序
  • 从小到大排序
function mpsort(num){
  for(let i=0;i<num.length;i++){
    for(let j=0;j<num.length-1-i;j++){
        if(num[j]>num[j+1]){
           let temp = num[j];
           num[j] = num[j+1];
           num[j+1] = temp;
          }
    }
  }
  return num
}
5、rem em px
  • 像素px是基于显示器屏幕分辨率而言的

  • rem 是基于html元素的字体大小来决定的,而em则根据使用父元素的大小决定,当使用rem单位,他们转化为像素大小

    取决于页跟元素的字体大小,即html将等同于字体大小乘以rem的值

    • 例如,根元素的字体大小为16px,10rem等同于160px,即10*16 =160px
  • em(与父元素字体大小有关)转化像素,大小取决于自身父级元素所设置的px值,父级元素字体大小乘以em值

    • 例如,父级元素字体大小为13px,10em将等同于130px,即13*10=130px
6、三栏(圣杯)等宽布局
  • 使用flex布局
.parent {
   display: flex;
   height: 300px;
   justify-content: space-between;
}
.left {
   background-color: pink;
   width: 33%;
}
.center {
   background-color: green;
   width: 33%;
}
.right {
   background-color: blue;
   width: 33%;
}
  • 使用浮动
.parent {
   width: 100%;
   height: 200px;
}
.left {
  float: left;
  width: 33%;
  background-color: red;
  height: 100%;
}
.center {
  float: left;
  width: 33%;
  height: 100%;
  background-color: blue;
}
.right {
  float: left;
  width: 33%;
  background-color: green;
}
  • 使用定位
.parent {
  position: relative;
  width: 100%;
  height: 300px;
}
.left {
  position: absolute;
  left: 0;
  width: 33%;
  height: 100%;
  background-color: red;
}
.center {
  position: absolute;
  left: 33%;
  right: 33%;
  width: 33%;
  height: 100%;
  background-color: aqua;
}
.right {
  position: absolute;
  right: 0;
  width: 33%;
  height: 100%;
  background-color: blue;
}
7、CSS三大特性
  • 层叠性
    • 相同的选择器设置相同的样式,一个样式会覆盖另一个样式(样式冲突的话遵循就近原则)
  • 继承性
    • 子标签会继承父标签的某些样式(和文字相关的样式、color,行高属性)
  • 优先级
    • 复合选择器会有权重叠加(但不会进位)
8、水平居中的方式
  • 行内元素
    • 将父级元素设置为块级元素,再给父元素设置text-align: center;
  • 块级元素
    +
9、正则表达式中的替换
str.replace(regexp|substr,newSubStr|function)
replace(/准备替换的字符/,'要替换的最终字符')
  • 一个将被newSubStr替换的字符串,其将被视为一整个字符串,而不是一个正则表达式。仅第一个匹配项会被替换
let str = 'abcdcrf'
console.log(str.replace('c','h'))//abhdcrf
  • g表示全局,将替换所有匹配的子串
let str = 'abchidfchc'
console.log(str.replace(/c/g,'h'))//abhhidfhhh
  • 将字符串中的数字用中括号括起来
  • \d表示0-9中任何一个数
let str = 'ash459u3t66'
console.log(str.replace(/(\d)/g,'[$1]'))//ash[4][5][9]u[3]t[6][6]
  • 将字符串中的每一个数字都*2
let str = 58pj216
console.log(str.replace(/(\d)/g,function(num){
return num*2
}))
//1016pj4212
10、数组去重的方法
利用数组的indexOf下标属性实现
let arr = [4,9,8,9,6,4,9,1]
function fun(arr){
  let newArr = []
  for(var i = 0;i<arr.length;i++){
    if(newArr.indexOf(arr[i]) === -1){
        newArr.push(arr[i])
    }
  }
  return newArr
}
fun(arr)
//[4,9,8,6,1]

利用includes方法
let arr = [4,9,8,9,6,4,9,1]
function fun(arr){
  let newArr = []
  for(var i = 0;i<arr.length;i++){
    if(!newArr.includes(arr[i])){
        newArr.push(arr[i])
    }
  }
  return newArr
}
fun(arr)
//[4,9,8,6,1]
11、typeof typeof typeof null的结果
console.log(typeof typeof typeof null)
1、typeof null //object
2、typeof 'object'//string
3、typeof 'string'//string
12、输出结果
var a = 1
function fun(){
 console.log(a)
 var a = 2
}
fun()
//undefined
//函数声明提升,所以函数会在 var a = 1的上面,所以在输出a的时候没有找到a的定义,输出undefined
13、margin-left 转化为marginLeft
function demo1(str){
var index=str.indexOf('-');//获取-的位置
// console.log(index);
str=str.replace('-','');
// console.log(str);
var c=str.charAt(index).toUpperCase();
var str0='';
//遍历字符串,替换指定字符
for(var i=0;i<str.length;i++){
if(i==index){
str0+=c;
}else{
str0+=str[i];
}
}
return str0;
}
let str = 'margin-left'
console.log(demo1(str))
//marginLeft


1、首先将字符串分隔成字符数组
2、遍历该数组,当遇到‘-’元素,删除该元素
3、将后面的字符元素变为大写
4、连接数组,返回结果
function changeStr(str){
  if(typeof(str) != 'string'){
    return '';
  }
  const strArr = str.split('');
  for(let i=0;i<strArr.length;i++){
      if(strArr[i] === '-'){
         //删除
         strArr.splice(i,1);
         //将此处改为大写
         if(i<strArr.length){
             strArr[i] = strArr[i].toUpperCase();
         }
      }
  }
  return strArr.join('');
}
console.log(changeStr('margin-left'));
//marginLeft
14、输出0123的另一种方法
  • 问题
for(var i=0;i<3;i++){
    setTimeout(()=>{
      console.log(i)
    },0)
}
//3 3 3
  • 解决办法
**使用let定义**
 for(let i=0;i<3;i++){
    setTimeout(()=>{
      console.log(i)
    },0)
}
//0 1 2
**使用闭包**
for(var i=0;i<3;i++){
  (function(j){
     setTimeout(function timer(){
       console.log(j)
     },500)
  })(i)
}
// 0 1 2 
**使用setTimeout的第三参数**
for(var i=0;i<3;i++){
  setTimeout((j)=>{
     console.log(j)
  },500,i)
}
//0 1 2 
15、防抖、节流
  • 用户触发事件过于频繁,只要最后一次事件的操作
    • 防抖
let inp = document.querySelector('input')
inp.oninput = debounce(function(){
   //业务逻辑
},500)

//闭包封装防抖函数
function debounce(fn,delay){
  let t = null;
  return function(){
     if(t !== null){
        clearTimeout(t);
     }
     t = setTimeout(()=>{
         fn();
     },delay)
  }
}
  • 节流
//节流,控制执行次数
//节流的作用:控制高频事件执行次数
window.onscroll = throttle(function(){
   //业务逻辑
},500)
   
function throttle(fn,delay){
   let flag = true; 
   return function(){
      if(flag){
         setTimeout(()=>{
            flag = true;
         },delay)
      }
      flag = false;
   }
}   
16、浮动
  • 浮动的特性:
    • 浮动元素会脱离标准流,浮动元素不再保留原先的位置
    • 浮动的元素会具有行内块元素的特性(任何元素都可以浮动)
  • 浮动的元素不会压住标准流的文字,绝对定位和固定定位会完全压住标准流所有内容
  • 浮动的影响
    • 脱离文档流,不占据页面空间,浮动层比标准层要高并且不占据页面空间
    • 浮动会将行内元素和块级元素转化为行内块元素
  • 为什么要清除浮动
    • 所有父盒子都必须要有高度吗?理想状态下,让子盒子撑开父盒子,正常情况下,若子盒子有浮动,父盒子不设高度的话,则无法撑开父盒子,就会影响后面的标准流元素,因为浮动的元素是脱离标准流的
  • 清除浮动的策略是:闭合浮动
    • 额外标签法(在浮动的最后一个元素,添加一个块级元素,其样式设置为clear:both)
    • 父级添加overflow属性(将其属性值设置为hidden,auto或scroll)
    • 父级添加after伪元素(伪元素选择器中写clear:both,display:block,是额外标签法升级版)
    • 父级添加双伪元素(父级使用before,after伪元素)
17、for…in 和 for…of
  • for…in(ES5提出)用于遍历数组的索引或者对象的键,会遍历对象所有的可枚举属性,包括原型,原型方法和属性。总是得到对象的key或数组、字符串的下标(下标顺序有可能不是按照实际数组的内部顺序)
  • for…of(ES6提出)用于遍历数组的元素,不便利原型方法和属性,总是得到数组、字符串的值,另外可以用于遍历map和set(遍历普通对象时会出错)
18、0.1+0.2 不等于0.3

js的number实现遵循IEEE 754标准,使用64位固定长度来表示,也就是标准的double双精度浮点数

看似有穷的数字,在计算机的二进制表示里确实无穷的,由于存储位数限制因此存在“舍去”,精度丢失就发生了

0.1的二进制表示的是一个无限循环的小数,js采用的是浮点数标准需要对这种无限循环的二进制进行截取,从而导致了精度的丢失,造成了不再是,截取之后变成0.100…001,0.2变成0.200…002,所以两者相加的数大于0.3

  • 解决

    Number((0.1+0.2).toFixed(1))
    toFixed方法可以指定运算结果的小数点后的指定位数的数字,使保留一位小数就是toFixed(1)
    
    把小数变为整数(乘倍数),再缩小会原来的倍数(除倍数)
    (0.1*10+0.2*10)/10
    
19、set/map
  • set是集合,map是字典。Weakset允许将弱对象存储在一个集合中
  • Set很容易实现交集
20、HTML新增的内容
  • 新增语义化标签
  • 新增表单标签
  • 表单元素
  • 表单属性
  • 表单事件
  • 多媒体标签
21、CSS3新增的
  • word-break 定义如何换行
  • word-wrap允许长的内容可以自动换行
22、2D、3D转换方法
  • rotate旋转translate(x,y)指定元素在二维空间得位移scale(n)定义缩放转换
  • perspective(n)为3D转换translate rotate scale
23、弹性盒子布局属性
  • flex-direction弹性容器中子元素的排列方式(主轴排列方式)

  • flex-wrap设置弹性盒子的子元素超出父容器是是否换行

  • flex-flow是felx-direction和flex-wrap得简写形式

  • align-item设置弹性盒子在侧轴上的对齐方式

  • align-content设置对齐方式

  • justify-content设置弹性盒子元素在主轴上的对齐方式

24、px em rem 的区别
  • px绝对长度单位,像素px是相对于显示器屏幕分辨率来说的

  • em相对长度单位,相对于对象内文本的字体尺寸

  • em的值并不是固定的,em会继承父级元素的字体大小,em中所有的字体都是相对于父元素的大小决定的

  • rem相对于html根元素的font-size

  • 1em=1rem=16px在body中加入font-size:62.5%这样直接就是原来的px数值除以10加上em就可以了

25、一个完整的AJAX请求包括五个步骤
创建XMLHTTPRequest对象
使用open方法创建http请求,并设置请求地址
xhr.open(get/post,url,async,true(异步),false(同步))经常使用前三个参数

设置发送的数据,用send发送请求
注册事件(给ajax设置事件)
获取响应并更新页面
26、NaN非数字
  • typeof NaN //number
  • 利用NaN的定义,用typeof判断是否为number类型并且判断是满足is NaN
  • 利用NaN是唯一一个不等于任何自身的特点 NaN == NaN (false)
  • 利用es6中提供的Object.is()方法,判断两个值是否相等
27、null与undefined的区别
  • 用if判断时,两者都会被转换为false
  • number转换的值不同number(null)为0 number(undefined) 为NaN
  • null表示一个值被定义了,但是这个值是空的
  • undefined变量声明了但是没有赋值
28、闭包
  • 定义在函数内部的函数
  • 特点
    • 函数嵌套函数
    • 函数内部可以引用外部的参数和变量
    • 参数和变量不会被垃圾回收机制回收
  • 使用
    • 读取函数内部的变量
    • 这些变量的值始终保持在内存中,不会在外层函数被调用后被自动清除
  • 优点
    • 变量长期贮存再内存中
    • 避免全局变量的污染
    • 私有成员的存在
  • 缺点
    • 会造成内存泄漏
29、js中常见的内存泄漏
  • 意外的全局变量
  • 被遗忘的计时器或回调函数
  • 脱离DOM的引用
  • 闭包
30、事件委托
  • 事件委托就是利用事件冒泡,只制定一个时间处理程序,就可以管理某一类型的所有事件。
  • 事件委托,称事件代理,是js中很常用的绑定事件的技巧,事件委托就是把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职务,事件委托的原理是DOM元素的事件冒泡
31、事件冒泡
  • 一个事件触发后,会在子元素和父元素之间传播,这种传播分为三个阶段
    • 捕获阶段(从window对象传导到目标节点(从外到里),这个阶段不会影响到任何事件)
    • 目标阶段(在目标节点上触发)
    • 冒泡阶段(从目标节点传导回window对象(从里到外)),事件委托/事件代理就是利用冒泡的机制把里层需要响应的事件绑定到外层
32、ES6新特性
  • let const
  • var声明的变量会挂载在window上,而let和const声明的变量不会
  • var声明的变量存在变量提升,let和const不存在变量提升
  • 同一作用域下var可以声明同名变量,let和const不可以
  • let和const声明会形成块级作用域
  • let暂存死区
  • const一旦声明必须赋值,不能用null占位,声明之后不能在修改,如果声明的是符合数据类型,可以修改属性
33、普通函数和构造函数的区别
  • 构造函数也是一个普通函数,创建方式和普通函数一样,但是构造函数习惯上首字母大写9

  • 调用方式不一样,普通函数直接调用,构造函数要用new关键字来调用

  • 调用时,构造函数内部会创建一个新对象,就是实例,普通函数不会创建新对象

  • 构造函数内部的this指向实例,普通函数内部的this指向调用函数的对象(如果没有调用对象,默认指向window)

  • 构造函数默认的返回值是创建的对象(也就是实例),普通函数返回值由return语句决定

  • 构造函数的函数名与类名相同

34、原型
  • 任何实例对象都有一个原型,也叫原型对象,这个原型对象由对象的内置属性__proto__指向它的构造函数的prototype指向的对象,即任何对象都是由一个构造函数创建的,但是不是每一个对象都有prototype,只有方法才有prototype
35、promise
  • promise是一种解决异步编程的方案。它可以获取异步操作的消息
  • promise有三种状态
    • pending初始状态也叫等待状态,
    • fulfiled成功状态,
    • rejected失败状态;
  • promise状态一旦改变,就不会再变
  • 创造promise实例后,它会立即执行
  • promise的两个特点
    • promise对象的状态不受外界的影响
    • promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可逆
  • promise的三个缺点
    • 无法取消promise,一旦创建它就会立即执行,无法中途取消
    • 如果不设置回调函数,promise内部抛出的错误,不会反映到外部
    • 当处于pending状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成
36、promise来解决两个问题
  • 回调地狱,代码难以维护
  • promise可以支持多并发的请求,获取并发请求中数据
  • 这个promise可以解决异步的问题,本身不能说promise是异步的
37、async
  • 函数前必须加一个async,异步操作方法前加一个await关键字,意思就是等一下,执行完了再继续走,注意:await只能在async函数中运行,否则会报错
  • Promise如果返回的是一个错误的结果,如果没有做异常处理,就会报错,所以用try…catch捕获一下异常就可以了
38、一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么
    1. 当发送一个 URL 请求时,不管这个 URL 是 Web 页面的 URL 还是 Web 页面上每个资源的 URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务器上启动一个 DNS 查询。这能使浏览器获得请求对应的 IP 地址
    2. 浏览器与远程 Web 服务器通过 TCP 三次握手协商来建立一个 TCP/IP 连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,然后服务器响应并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
    3. 一旦 TCP/IP 连接建立,浏览器会通过该连接向远程服务器发送 HTTP 的 GET 请求。远程服务器找到资源并使用 HTTP 响应返回该资源
    4. 此时,Web 服务器提供资源服务,客户端开始下载资源
39、For循环与map循环有什么区别
  • for遍历对象自身的和继承可枚举的属性,也就是说会包括哪些原型链上的属性
  • map方法不会对空数组进行检测,map会返回一个新数组,不会对原数组产生影响
40、同步、异步
  • 同步,阻塞的
  • 异步,非阻塞的
41、重绘和回流
  • 当渲染树中的一部分或者全部因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就叫回流
  • 在回流的时候,浏览器会使渲染树中收到影响的部分失效,并重新构造这部分呢渲染树,完成回流之后,浏览器会重新绘制受影响的部分到屏幕中,这就是重构
42、HTTP
  • http叫做超文本传输协议,是互联网应用最广泛的一种网络协议
  • 特点,基于请求-相应的模式 无状态保存 无连接
43、HTTP和HTTPS的区别
  • http是超文本传输协议,信息是明文传输,https是具有安全性的sl解密传输协议
  • http和https连接方式完全不同,端口也不同,http是80,https是443
  • http的来凝结很简单,是无状态的,https协议是由ssl+http协议构建的可进行加密传输,身份认证的网络协议,比http协议安全
44、原型和继承,prototype,call和apply继承的区别
  • apply()接收两个参数,一个是函数运行的作用域(this),另一个是参数数组
  • call()方法第一个参数与apply()方法相同,但传递给函数的参数必须列举出来
45、箭头函数与普通函数的区别
  • 箭头函数是匿名函数,不能作为构造函数,不能使用new
  • 箭头函数不能绑定arguments,要用rest参数解决
  • 箭头函数没有原型属性
  • 箭头函数的this永远指向其上下文的this
  • 箭头函数不能绑定this,会捕获其所在上下文的this值,作为自己的this值
46、js内存泄漏
  • 内存泄漏是指一块被分配的内存既不能使用又不能回收,直到浏览器进程结束
  • 释放内存的方法:赋值为null
47、网站的文件和资源进行优化
  • 1、文件合并(目的是减少http请求)

  • 2、文件压缩(目的是直接减少文件下载的体积)

  • 3、使用cdn托管资源

  • 4、使用缓存

  • 5、gizp压缩你的js和css文件

  • 6、meta标签优化(title,description,keywords)、heading标签的优化、alt优化

  • 7、反向链接,网站外链接优化

48、常见的http状态码
  1. 100:告诉客户端应该继续发请求
  2. 200:表示服务器已经成功接收请求
  3. 204:表示服务器已经接受了请求,但是还没有处理,而且这个请求最终会不会处理还不确定
  4. 301:客户端请求的网页已经永久移动到新的位置,当链接发生变化时,返回301代码告诉客户端链接的变化,客户端保存新的链接,并向新的链接发出请求,已返回请求结果
  5. 404:请求失败,客户端请求的资源没有找到或者是不存在
  6. 500:服务器遇到未知的错误,导致无法完成客户端当前的请求
  7. 503:服务器由于临时的服务器过载或者是维护,无法解决当前的请求
49、get和post的区别
  • get是从服务器上获取数据,post事项服务器传送数据
  • 在客户端,get通过url提交数据,数据在url中可以看到,post方式。数据放在html header中提交
  • 安全性问题
    • get提交数据最多只能有1024字节,post没有限制
50、Vue
  • Vue是一套构建用户界面的渐进式自底向上增量开发的MVVM框架,vue核心只关注视图层
  • 核心思想:数据驱动(视图的内容随着数据的改变而改变)
  • 组件化(可以增加代码的复用性、可维护性、可测试性,提高开发效率,方便重复使用,体现了高内聚低耦合)
51、MVVM思想
  • 模型 视图 vm是v和m连接的桥梁,当模型层数据修改时,VM层会检测到,并通知视图层进行相应的修改
52、vue的单向数据流
  • 父级prop的更新会向下流动到子组件中,每次父组件发生更新,子组件所有的prop都会刷新为最新的值
  • 数据从父组件传递给子组件,只能单向绑定,子组件内不能直接修改父组件传递过来的数据(可以使用data和computed解决)
53、计算属性
  • 计算属性是用来声明式的描述一个值依赖了其他的值,当它依赖的这个值发生改变时,就更新DOM

    当在模板中把数据绑定到一个计算属性上时,vue会在它依赖的任何值导致该计算属性改变时更新DOM

    每个计算属性都包括一个getter和setter,读取时触发getter,修改时触发setter

54、跨域的解决方法
  • 后台修改header
  • 使用jq提供jsonp
  • 用http-proxy-middleware(配置代理服务器的中间件)
55、vue的生命周期
  • vue的生命周期就是vue实例创建到实例销毁的过程。期间会有8个钩子函数的调用
  • beforeCreate(创建实例)
  • created(创建完成)
  • beforeMounte(开始创建模板)
  • mounted(创建完成)
  • beforeUpdate(开始更新)
  • updated(更新完成)
  • beforeDestroy(开始销毁)
  • destroyed(销毁完成)
56、vue生命周期的作用
  • 给了用户在不同阶段添加自己的代码的机会
57、DOM渲染在哪个生命周期阶段完成
  • 在mounted周期中就已经完成
58、Vue路由模式hash和history
  • Hash模式地址栏中有#,history没有,history模式下刷新,会出现404情况,需要后台配置

    使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值

    可以使用 hashchange 事件来监听 hash 值的变化

59、对vue 中keep-alive的理解
  • keep-alive是vue的内置组件,当它动态包裹组件时,会缓存不活动的组件实例,它自身不会渲染成一个DOM元素也不会出现在父组件链中
  • 作用:在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间以及性能消耗,提高用户体验。
60、typeof null 结果为什么是object
  • 不同的对象在底层都表示二进制,在JavaScript中二进制前三位都为0的话会被判断为object类型
  • null的二进制表示全是0,自然前三位是0,所以执行typeof时会返回object
61、new关键字的执行过程
  • new 构造函数可以在内存中创建一个空的对象
  • this就会指向新创建的空对象
  • 执行构造函数里面的代码,给这个空对象添加属性和方法
  • 返回这个对象
62、严格模式下的this指向
  • 严格模式下函数的this指向undefined

  • function fun() {
      'use strict'
      console.log(this);
    }
    fun()  //undefined
    
  • 类中所有的方法,在局部默认开启了严格模式,this不敢指向window所以指向了undefined

  • class fun {
      constructor(name, age) {
        this.name = name
        this.age = age
      }
      stady() {
        console.log(this);
      } 
    }
    const f0 = new fun('ooo', 3)
    f0.stady() 
    //fun(name:'ooo',age:3)
    //undefined
    
63、同步异步的执行顺序
  1. 同步
  2. process.nextTick()
  3. 微任务
    promise.then()
  4. 宏任务
    计时器 、ajax
  5. setImmediate
64、原型、原型链
  • 什么是原型

    • 原型是对象

    • 每一个对象都有他的原型对象,他可以使用自己原型对象上的所有属性和方法

    • let cat = {
        name: '阿猫'
      }
      cat.__proto__.eat = function () {
        console.log('我爱吃鱼');
      }
      cat.eat()
      //我爱吃鱼
      
  • 获取原型的方法

    • 1、通过对象的———__proto__获取

      let cat = {
        name: '阿猫'
      }
      cat.__proto__.eat = function () {
        console.log('我爱吃鱼');
      }
      cat.eat()
      //我爱吃鱼
      
    • 2、通过构造函数的prototype属性拿到原型

      function Cat(name, age) {
        this.name = name
        this.age = age
      }
      
      let cat = new Cat('阿毛', 3)
      Cat.prototype.eat = function () {
        console.log('我是一只爱吃鱼的猫');
      }
      cat.eat()
      // 我是一只爱吃鱼的猫
      
    • 3、通过类的prototype属性

      class Cat {
        constructor(name, age) {
          this.age = age
          this.name = name
        }
      }
      
      let cat = new Cat()
      Cat.prototype.eat = function () {
        console.log('我是一只爱吃鱼的猫');
      }
      cat.eat()
      //我是一只爱吃鱼的猫
      
  • 原型的作用

    • 扩展对象

      let date = new Date()
      Date.prototype.formate = function () {
        let year = this.getFullYear()
        let month = this.getMonth()
        let day = this.getDate()
        return `${year}年${month}月${day}日`
      }
      console.log(date.formate());
      //2021年10月18日
      
65、ES6中的 类
  • class Cat {
      constructor(name, age) {
        this.age = age
        this.name = name
      }
    }
    
    let cat = new Cat()
    
  • 类的继承extends

    // 普通用户
    class User {
      constructor(username, password) {
        this.username = username
        this.password = password
      }
      login() {
        console.log('登录');
      }
    }
    // 系统管理员   可以继承普通用户使用普通用户的所有属性和方法
    class Admin extends User {
      deleteOne() {
        console.log('我是系统管理员,我可以删除一个普通用户');
      }
    }
    let user = new User('张三', 123456)
    
    let admin = new Admin()
    console.log(admin.login());
    //登录
    console.log(admin.deleteOne());
    //我是系统管理员,我可以删除一个普通用户
    
66、ES5 继承,基于原型链的继承
  • 使用prototype属性实现

    function User(username, password) {
      this.username = username
      this.password = password
      this.login = function () {
        console.log('登录');
      }
    }
    
    function Admin() {
      this.deletePerson = function () {
        console.log('我可以删除一个人');
      }
    }
    
    // Admin的原型对象是Uer的实例 所以Admin可以使用他的原型对象也就是User的所有属性和方法
    Admin.prototype = new User()
    
    let admin = new Admin()
    console.log(admin.deletePerson());
    //我可以删除一个人
    console.log(admin.login());
    //登录
    
67、原型链
  • 对象有原型

  • 对象的原型是一个对象

  • 所以原型上有原型,原型上还有原型,就形成了一条原型链

    Admin --> prototype --> prototype --> ... --> Object.prototype
    
    function User(username, password) {
      this.username = username
      this.password = password
      // this.login = function () {
      //   console.log('登录');
      // }
    }
    
    function Admin() {
      this.deletePerson = function () {
        console.log('我可以删除一个人');
      }
    }
    
    
    Object.prototype.login = function () {
      console.log('Object原型上的login方法');
    }
    
    // Admin的原型对象是Uer的实例 所以 Admin可以使用他的原型对象也就是User的所有属性和方法
    Admin.prototype = new User()
    
    let admin = new Admin()
    console.log(admin.deletePerson());
    //我可以删除一个人
    console.log(admin.login());
    //Object原型上的login方法
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值