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 到页面加载显示完成,这个过程中都发生了什么
-
- 当发送一个 URL 请求时,不管这个 URL 是 Web 页面的 URL 还是 Web 页面上每个资源的 URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务器上启动一个 DNS 查询。这能使浏览器获得请求对应的 IP 地址
- 浏览器与远程 Web 服务器通过 TCP 三次握手协商来建立一个 TCP/IP 连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,然后服务器响应并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
- 一旦 TCP/IP 连接建立,浏览器会通过该连接向远程服务器发送 HTTP 的 GET 请求。远程服务器找到资源并使用 HTTP 响应返回该资源
- 此时,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状态码
- 100:告诉客户端应该继续发请求
- 200:表示服务器已经成功接收请求
- 204:表示服务器已经接受了请求,但是还没有处理,而且这个请求最终会不会处理还不确定
- 301:客户端请求的网页已经永久移动到新的位置,当链接发生变化时,返回301代码告诉客户端链接的变化,客户端保存新的链接,并向新的链接发出请求,已返回请求结果
- 404:请求失败,客户端请求的资源没有找到或者是不存在
- 500:服务器遇到未知的错误,导致无法完成客户端当前的请求
- 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、同步异步的执行顺序
- 同步
- process.nextTick()
- 微任务
promise.then() - 宏任务
计时器 、ajax - 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方法