转换时间戳:new Date(parseInt(item.createTime)).toLocaleString().replace(/:\d{1,2}$/,' ')
router.beforeEach((to, from, next) => {
// console.log(store);
if (store.state.use.length==0) {
if (to.name == "Login") {
next()
} else {
next("/login")
}
} else {
if (to.name == "Login") {
next("/")
} else {
next()
}
}
next()
})
函数没有return返回值,返回的是undefined ---------!!!
:style="{backgroundImage: 'url(' + (item.pic_url) + ')', backgroundSize:'contain'}" -------背景图片
node,vue,git
linux系统:用命令行打开应用,系统特别稳定,服务器常用系统
svn:小乌龟,类似git也是代码管理工具
git密码990328jqk
git:世界上最广泛的代码管理工具---github,码云
类似于一个仓库,存放代码,适合多人开发,每个人互不影响
本地---暂存区---仓库
1 安装git
百度 搜索 git
代开git官网
下载 -- 一路回车安装
桌面点击右键 -- git bash
注册gitee并且新建仓库
百度 打开 码云
注册 ---- 进入 码云
新建远程仓库:
右上角 + ,新建仓库
克隆 远程仓库到本地
桌面新建文件夹,文件夹内 右键 git bash
git clone '远程仓库地址'--------吧仓库拉到本地
例如: git clone https://gitee.com/courseP7/asdv.git
本地到远程 *****
1. git add . 将本地的暂存------吧要传仓库的数据存到暂存区
2. git commit -m "描述信息"
git config --global user.email "你的邮箱"
git config --global user.name "你的名字"
3. git push --------上传仓库
如果别人传过代码,先git pull 拉一下,再git push 上传
.gitignore忽略某个文件的变动
v-clock-----------防止页面闪烁
v-if----动态添加或删除dom节点,v-show(css的display)
jquery的核心的元素选择器
v-model 修饰符 :
.trim:自动过滤用户输入的首尾空格
vue里通过ref获取节点,
this.$refs['']
vue生命周期:---------------!!!!!!!!!!!!
页面的生命周期,一个页面从开始到销毁的过程
创建: beforCreate 实例创建之前,不能获取data数据,
created实例创建之后,可以获取data数据
挂载: beforeMount 组件挂载之前,可以获取data数据,不能获取dom元素,
mounted,组件挂载之后,可以获取data数据,能获取dom元素
更新: beforeUpdate 数据更新,视图更新之前
updated 视图更新之后
销毁: beforeDestroy 页面销毁之前,
destroyed,定时器、监听销毁之后
组件激活:activated
组件失活:deactivated
捕获子组件的错误时调用 : errorCaptured
Vue3.0中的生命周期做了一些改动:
beforeCreate -> setup() 开始创建组件之前,创建的是data和method
created -> setup()
beforeMount -> onBeforeMount 组件挂载到节点上之前执行的函数。
mounted -> onMounted 组件挂载完成后执行的函数
beforeUpdate -> onBeforeUpdate 组件更新之前执行的函数。
updated -> onUpdated 组件更新完成之后执行的函数。
beforeDestroy -> onBeforeUnmount 组件挂载到节点上之前执行的函数。
destroyed -> onUnmounted 组件卸载之前执行的函数。
十、Vue2和vue3的区别
1.双向数据绑定原理发生了改变,使用proxy替换Object.defineProerty,使用Proxy的优势:
可直接监听数组类型的数据变化
监听的目标为对象本身,不需要像Object.defineProperty一样遍历每个属性,有一定的性能提升
可直接实现对象属性的新增/删除
2.默认使用懒加载
在2.x版本里。不管数据多大,都会在一开始就为其创建观察者,在数据很大时,就会造成性能的问题。在3.x中,只会对渲染出来的数据创建观察者,而且3.x的观察者更高效。
3.3.0新加入了TypeScript以及PWA支持
4.重构Virtual DOM
模板编译时的优化,将一些静态节点编译成常量
Slot优化,将slot编译为lazy函数,将slot的渲染的决定权交给子组织
5.生命周期有了一定的区别
Vue2--------------vue3
beforeCreate -> setup() 开始创建组件之前,创建的是data和method
created -> setup()
beforeMount -> onBeforeMount 组件挂载到节点上之前执行的函数。
mounted -> onMounted 组件挂载完成后执行的函数
beforeUpdate -> onBeforeUpdate 组件更新之前执行的函数。
updated -> onUpdated 组件更新完成之后执行的函数。
beforeDestroy -> onBeforeUnmount 组件挂载到节点上之前执行的函数。
destroyed -> onUnmounted 组件卸载之前执行的函数。
activated -> onActivated 组件卸载完成后执行的函数
deactivated -> onDeactivated
父子组件的生命周期:
先执行父组件的beforeCreate、created、beforeMount、
然后执行子组件的beforeCreate、created、beforeMount、mounted
然后父子间mounted挂载完成
销毁:父组件先准备销毁 beforeDestroy,
然后销毁子组件 beforeDestroy,destroyed,
最后销毁父组件 destroyed
父传子:
表单修饰符
.number
@click.native native原生,触发父组件中子组件的@click事件
.懒加载lazy
lang 定义语言
scoped 防污染
vue2的data为什么是函数:闭包
闭包:一个作用域可以访问另外一个函数内部的局部变量
监听属性:
watch:{
handler(newval,oldval){
console.log(newval,oldval)
},
deep:true;-----深度监听
immediate:true------立即监听
}
计算属性有缓存 !!
计算属性、过滤器一定有返回值return,
监听属性无return
过滤器:
对常用文本的格式化,常用于格式化时间、价格,
过滤器没有this指向----------!!!!!!!!
全局过滤器、局部过滤器
局部过滤器:
<p>价格:{{ price | filterPrice(1,2) | filterPrices }}</p> | 管道符-----price变量,filterPrice过滤器名
filters: {
filterPrice(price,a,b){
return this.price
}
},
filterPrices(str){
return this.price+ str --------str这个参数就是filterPrice
}
过滤器第一个参数,是管道符前面的数据,第二个第三个是函数括号内的参数
过滤器可以串联使用,下一个过滤器第一个参数永远是上一个过滤器返回出来的数据
全局过滤器:
vue.filter('filtertime',(time)=>{
return time
})
数据类型:
一般:number、string、boolean、undefined、null,存放在栈里
引用(复杂):object、array、function、date、reg,存放在堆里,栈里有个指针指向堆存放的位置
判断数据类型:
1、typeof : typeof null 返回的是小写的object !!!!!!!!!
2、instanceof : console.log( [ ] instanceof Array )
3、constructor 构造器 :arr.constructor ==Array
4、对象原型上的tostring 方法 ,这种方法可以判断所有的
if( Object.prototype.toString.call( ' ' ).indexOf( ' String' )>-1 {
console.log()
}
prototype 原型链,call 改变this指向
深复制潜复制:
1、let obj=JSON.parse(JSON.stringify(obj))
2、let obj={ ...obj }
3、递归查询
递归:一个函数在内部可以调用其本身,这个函数就是递归函数
VUEX:状态管理工具
state: 存放状态/数据的
getters: vuex的计算属性
mutations: 唯一改变state数据的工具
actions: 异步操作,需要经过mutations内的方法改变state
module: 模块化,大型项目
例子:
modules: {
one:{
state:{
num:0
}
}
}2
<p>{{$store.state.one.num}}</p>
mapState、mapMutations、mapActions、mapGrtters、
mapState、mapGrtters、在computed
例子:
computed :{
...mapState({ })
}
mapActions、mapMutations、在methods
本地存储:
浏览器的存储:localStorage、sessionStorage、cookie
相同点: 都可以存储数据,并且存储只跟域名走
不同: 1、大小 localStorage、sessionStorage 5M,cookie 4K
2、传输 cookie会跟着请求来回发送,而localStorage、sessionStorage 不会
3、localStorage 永久存储 / sessionStorage 关闭当前会话/关闭页面就会消失
4、cookie 可以设置过期时间;如果不设置,会话关闭自动失效
seo检索 title、content、keyword的关键字
编程式导航:this.$router.push
声明式导航: <router-link to="/"></router-link>
路由重定向:redirect
路由别名:alias:"/"
路由:
hash 和history
hash 路径有#号,history路径没#号
路由传参:
三种:
分别是query,params,动态路由传参
接收:
通过query方式传递过来的参数一般是通过this.$route.query接收
通过params方式传递过来的参数一般是通过this.$route.params接收
通过动态路由传参方式传递过来的参数一般是通过this.$route.params接收
query使用path和name传参跳转都可以,而params只能使用name传参跳转。
传参跳转页面时,query不需要再路由上配参数就能在新的页面获取到参数,
params也可以不用配,但是params不在路由配参数的话,当用户刷新当前页面的时候,参数就会消失。
也就是说使用params不在路由配参数跳转,只有第一次进入页面参数有效,刷新页面参数就会消失。
500-------服务器报错
400-------客户端错误,404路径错误
300-------重定向错误
200-------成功
Maximum call stack size exceeded 堆栈溢出----死循环
路由的守卫:
1、全局守卫:
前置守卫:router.beforeEach
// router.beforeEach((to, from, next) => {
// if (!store.state.list && to.name != "loding") {
// next("/loding")
// return
// }
// if (store.state.list && to.name == "loding") {
// next("/")
// return
// }
// next()
// })
后置钩子函数:router.afterEach
router.afterEach((to,from,next)=>{
console.log(to)
console.log(from)
console.log(next) //没有
})
组件守卫:
在页面写,跟data同级:
1、beforeRouteEnter(to,from,next){
} 路由进入前
2、beforeRouteUpdate(to,from,next){
} 路由更新
3、beforeRouteLeave(to,from,next){
} 路由离开
单个守卫(独享的):
写在路由里
beforeEnter(to,from,next){
next()
}
keepalive:
缓存不活动的动态组件,而不是销毁他们,
也不会出现在父组件中作为标签使用
<keep-alive>
<组件名></组件名>
</keep-alive>
动态组件:
<components :is=""></components>
还能缓存页面:
路由元信息:
在页面的路由配置下写:
meta:{
noneedCache:true
},
keep-alive包裹的所有非页面1路径,会把数据缓存在内存中
<keep-alive>
<router-view v-if="$route.name!=='页面1路径'"></router-link>
</keep-alive>
页面1没有被keep-alive包裹,所以数据不会缓存
<router-view v-if="$route.name=='页面1路径'"></router-link>
白名单,黑名单
白名单有缓存,黑名单没缓存
黑名单:exclude,白名单include ,最大数max
黑名单exclude 需要不被缓存的页面 放进黑名单的数组内
在静态资源管理内创建一个js文件,导出一个数组,数组内放置需要进入黑名单的组件名
在定义坑的页面引入赋值 作为keep-alive的黑名单的属性 值使用
<keep-alive :exclude="[ '页面1路径' , '页面2路径' ]">
<router-view></router-link>
</keep-alive>
白名单include 需要被缓存的页面 放进白名单的数组内
最大数max 假如设置的max为10,那么如果被黑名单限制的页面数量超过10时,
会从1的地方删除,然后把后面的往前依次往前面推进一位
事件传播流程:
捕获》目标源》冒泡
捕获:从外到内
冒泡:从里到外
this指向:
谁调用指向谁
工作中 let vm=this,
下面用 vm
构造函数内this指向 -- new 出来的实例化对象
箭头函数 ------ 不会改变this指向
闭包:closure
函数嵌套函数
好处:一直保存
坏处:造成内存泄漏
什么是Vue.nextTick()??
定义:在下次 DOM 更新循环结束之后执行延迟回调。
在修改数据之后立即使用这个方法,获取更新后的 DOM。
什么时候需要使用:
在created钩子函数需要进行dom操作的候,
进行的dom操作要放在nextTick中,
因为created时dom并未渲染
ref和refs
要想在vue中操作dom元素,就需用ref属性进行注册
<p ref="p"></p>
this.refs[ 'p' ]
mixin ----混入
抽离出公共功能js的东西
新建一个js文件,导出
在页面引入 import js文件名 from "路径"
注册:mixins:[ ]
混入对象的钩子函数将在组件自身的钩子函数之前调用
自定义指令:
全局自定义指令 vue.directive、
局部自定义指令 directives
directives: {
vcolor(el, bind, vnode) {
el.style.color = bind.value;
}
},
vcolor ----自定义指令名
el -------指令所绑定的元素
bind ------- 一个对象
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
Vnode:Vue编译生成的虚拟节点
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
项目中:拖拽
$set
当双向数据绑定失败的时候使用$set
简单的来说,往对象中新增一条属性 ; 如果对象中原来没有这个key,新增的key是无法双向绑定的。
用法:this.$set(this.userProfile, 'age', 27)
ajax的核心对象是内嵌到浏览器的,所以再什么地方都能用
主要是用来实现页面的局部刷新的一门技术
核心对象:XMLHttpRequest
1、实例化对象 var 变量名 =new XMLHttpRequest()
2、建立链接 变量名.open('请求方式','请求的路径','同步异步')
3、发送请求,如果说要传参,可以写在这个里面
var xhr =new XMLHttpRequest( )
xhr.open('get','路径')
xhr.send( )
xhr.onreadystatechange=function () {
if(xhr.readyState==4 && xhr.status==200){
console.log(JSON.parse(xhr.response))
}
}
没用过fetch,用过axios
fetch、axios 是vue请求的插件
原型:
prototype 显性原型
__proto__ 隐性原型 如果放在这个上,就相当于放在vue上
跨域:
跨域是浏览器的同源策略引起的 协议域名端口不一致就是跨域
解决跨域的办法?
服务端的代理 jsonp nginx反向代理等等
服务器设置不跨域 设置的是响应头 res.setHeader('Access-Control-Allow-Origin','*') *代表所有
服务端的代理 浏览器
在vue的根目录新建一个文件 vue.config.js
module.exports= {
devServer:{
port:'' 端口号
proxy:{ //代理
'/api': { //请求路径中如果有'/api'字段 会自动接到target
target:'http://localhost:3000/', //目标源
changeOrigin:true,//允许跨域
pathRewrite: {
'/api':'' //路径重写
}
}
}
}
跨域
跨域是浏览器的同源策略造成的 //小程序是依托于微信的不依赖于浏览器,所以不会产生跨域的问题
同源策略的产生是为了安全的考虑 同源:协议,域名,端口号完全一致
协议,域名,端口有一个不相同就会产生跨域
如何处理跨域:1:服务端设置不跨域 2:jsonp的方式 3:服务端的代理 4:nginx反向代理等等
1》服务端设置不跨域: 在该服务器的setHeader响应头里面设置允许所有的请求都放行 例:res.setHeader('Access-Control-Allow-Origin','*') //*号代表放行所有的请求
2》jsonp 浏览器不会阻止script标签引入 用script标签引入服务器接口并传递一个函数 前端定义函数传给后台 后台服务器调用函数并传参
3》vue服务端的代理 在vue的根目录下新建一个vue.config.js 利用node的服务器直接跟请求的服务器直接请求 node服务
会自动把路径改为设置的路径并遇见api就放行,请求别的接口的时候进行路径重置
语法:module.exports={
devServer:{//控制node服务
proxy:{ //代理
'/api':{ //看到请求路径中只要有api字段 就会直接把这个字段转接到target这个接口上
target:"http://localhost:3000/", //目标源
changeOrigin:true, //开启跨域
pathRewrite:{
'/api':'' //路径重写 把api置为 ' '
}
}
}
}
}
html绑定事件的方式:
1、绑定事件,标签上直接绑定
<p οnclick="console.log(1)">哈哈</p>
2、获取元素绑定
document.querySelector('p').οnclick=function(){
console.log(1)
}
3、添加事件监听
document.queryselector('p').addEnentListener('click',()=>{consloe.log('1')},false或true)//false为冒泡,true为捕获 注:有三个参数,第一个代表什么事件,第二个是函数,第三个为true或false
vue3监听属性:
watch(num,(newVal,oldVal)=>{
console.log(newVal,oldVal)
},{immediate:true})
watchEffect:和VUE2 的计算属性类似,
依赖值发生改变自动触发,
进入页面就触发一次
vue3父子传值:
provide和inject
在父组件用 provide('num',num)
类似本地存储的写法,
在子组件用变量接收:
const num=inject('num')
ES6新增的属性和方法:
1、声明变量
let、const
暂时性的死区:用let和const声明变量的上面
用let 声明一个变量在当前作用域范围内,
不能使用这个变量,也不能重新声明这个变量
1、暂时性的死区
2、不能重复声明
3、不存在变量提升 -------var存在变量提升
let、const的区别:
const声明的是一个常量,正常情况下不能更改,
当声明引用数据类型(复杂数据类型:object、array)时,
是说他的堆存储的地址不能改,是es6最简单的一个块级作用域
块级作用域:{ } 包裹的就是块级作用域
2、数据类型
symbol:代表唯一的,简单的数据类型
使用 typeof 可以判断 symbol 数据类型为 symbol
应用场景:用来声明唯一值,给对象添加私有属性
3、解构赋值
es6允许按照一定的结构对变量进行赋值;这个就叫解构赋值
针对数组和对象
4、Promise
是异步编程的一种方案,
有三个状态:pending 初始状态、fulfiled成功状态、rejected失败状态
new promise 实例化
是一个函数,接受两个函数作为参数:resolve、reject
resolve是操作成功,状态变成fulfiled
reject是操作失败,状态变成rejected
promise状态一经改变,不会再变,是不可逆的
用.then()方法调用成功状态
.catch()调用失败状态
.finally()成功和失败都会调用
promise有 all()方法,等待所有异步操作都执行成功
还有race()方法,就是赛跑的意思,
所有的异步操作哪个先执行结束,无论成功失败,就执行他
5、箭头函数
参数:如果没有参数或者欧多个参数,参数要用()包括起来
箭头函数没有this指向
箭头函数不能作为构造函数
没有arguments
阮一峰
generator:
声明:function 和函数名之间加一个 *
例子:function * fn(){}
特点:
也是异步编程的一个解决方案;分段执行
启动函数:next()
function * fn(){
console.log(1)
}
let g=fn()
g.next()
分段执行的时候,需要配合 yield 使用
async 和 await
ES6 新增的属性和方法
1. 声明变量 let. Const
2. 一个基本的数据类型 symbol
3. 解构赋值
4. promise
5. 箭头函数
6. findIndex
7. generator
8. async await
9. Class
vue双向数据绑定
vue采用了数据劫持 结合发布者和订阅者模式 ,通过Object.defineProperty来劫持各个属性的setter,getter。
在数据变动的时候发布给订阅者,触发监听从而来更新试图
Obsrever能够对数据进行监听,一旦变化就通知给订阅者,
complie对每个元素节点指令进行扫描、解析。
watcher 作为obsrever和complie的桥梁,能够收到每个属性的变动通知,执行指令绑定的响应回调函数,更新视图
面向对象编程-三要素:封装 继承 多态
继承 属性的继承 方法的继承
es6出来前jst通过原型构造函数来实现继承的 es6出来后class(类)
原型链添加属性和方法,原型链上的属性和方法会被多个实例共享
函数没有return返回值,返回的是undefined ---------!!!
构造函数不能用变量声明的方式不能用箭头函数 大写
原型链继承可以继承 原型链上的属性和方法 可以继承实例的方法
每个构造函数有一个显式原型 prototype
每个实例对象有一个隐式原型__proto__
每个实例对象的隐式原型指向自身构造函数的显式原型
原型链
获取对象属性时,如果对象本身没有这个属性,
那就会去他的隐式原型_ _proto_ _上去找,如果还找不到,会一直找到最顶层的
继承的方法
实例化继承:
1原型链的继承
可以继承原型上的属性和方法
可以继承构造函数内的属性和方法
不能传参
原型链添加属性和方法,原型链上的属性和方法会被 多个实例共享
function Person(name,age) {
this.name=name
this.age=age
this.eat=function() {
console.log(this.name+'吃饭');
}
}
function Web() {
}
Web.prototype=new Person()
2 伪造对象继承
call apply bind 直接把this指向另一个实例
伪造对象 不好:不能继承原型上的属性和方法
3组合继承就是把伪造对象继承和原型链的继承结合起来
function Person(name, age) {
this.name = name
this.age = age
this.eat = function () {
return `${this.name}会吃饭`
}
}
Person.prototype.gender = '男'
Person.prototype.run = function () {
return `下雨了${this.name}会往家跑`
}
function Web(name, age) {
// 伪造对象的方式
Person.call(this, name, age)
}
Web.prototype= Person.prototype
let w=new Web('zs',18)
console.log(w.name);
console.log(w.age);
console.log(w.gender);
ES6类
class People {
//属性固定写法
constructor(name, age) {
this.name = name
this.age = age
}
方法
eat() {
console.log(this.name + '会吃饭');
}
}
类继承
class Web extends People {
constructor(name, age) {
super(name, age)// 调用 父类的 constructor
}
}
let w = new Web('zs', 18)
console.log(w.name);
w.eat()
字符串方法:
1、遍历
2、查找 :indexOf
3、去除首尾空格 :trim()
4、截取 :slice()
5、转数组:split ( )
6、十、大小写转换
(1)toLocaleLowerCase() --转化为本地格式的小写
(2)toLocaleUpperCase() --转化为本地格式的大写
(3)toLowerCase()-----------把字符串转换为小写
(4)toUpperCase()-----------把字符串转换为大写
数组的高阶函数:
1.forEach()
用法:array.forEach(function(item,index){})
没有返回值,只是单纯的遍历
2.map()
用法:array.map(function(item,index){})
遍历并对其进行操作,返回新数组,原数组不变
3.filter()
用法:array.filter(function(item,index){})
筛选符合条件的元素并返回新数组,原数组不变
4.find()
用法:array.find(function(item,index){})
返回符合条件的第一个元素,原数组不变
5.every()
用法:array.every(function(item,index){})
检测是否所有元素都符合条件,返回true或false
6.some()
用法:array.some(function(item,index){})
检测数组中是否有满足条件的元素,返回true或false
7.reduce()
用法:array.reduce((sum, item) => […sum, …item.data], [])
参数一:回调函数
参数一:累加的值
参数二:每一项的值
参数三:下标
参数四:数组
参数二:初始值
// item.data 不是数组 就不用加…
foreach和map:
共同点
(1)只能遍历数组
(2)都是循环遍历数组中的每一项
(3)每一次执行匿名函数都支持三个参数,数组中的当前项item,当前项的索引index,原始数组input
(4)匿名函数中的this都是指window
不同:
foreach没有返回值,map有返回值
总的来说 map 的速度大于forEach。
map会返回一个新的数组,不会改变原来的数组,forEach不会返回新数组,允许对原数组进行修改。
都有参数,item, index arr 。
内部匿名函数的this指向都是window。
为什么data是一个函数:
1.vue中组件是用来复用的,为了防止data复用,将其定义为函数。
2.vue组件中的data数据都应该是相互隔离,互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响,就需要通过data函数返回一个对象作为组件的状态。
3.当我们将组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,拥有自己的作用域,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
4.当我们组件的date单纯的写成对象形式,这些实例用的是同一个构造函数,由于JavaScript的特性所导致,所有的组件实例共用了一个data,就会造成一个变了全都会变的结果。
闭包:
1、概念
闭包函数:声明在一个函数中的函数,叫做闭包函数。
闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
2、特点
让外部访问函数内部变量成为可能;
局部变量会常驻在内存中;
可以避免使用全局变量,防止全局变量污染;
会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
4.事件委托的原理和作用?
原理:给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。
作用:
我们只操作了一次 DOM ,提高了程序的性能。
动态新创建的子元素,也拥有事件。
14.null和undefined的区别?
null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。
当声明的变量还未被初始化时,变量的默认值为undefined。 null用来表示尚未存在的对象
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2)调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
null表示"没有对象",即该处不应该有值。典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
原型和原型链:
__proto__隐式原型
prototype显示原型
每个对象都有一个隐式原型,每一个函数都有一个显示原型,contructor构造器
每个实例对象的隐式原型都指向当前函数的显示原型,因为他们相等
声明一个没有原型的对象:let obj=object.create(null)
3. constructor
每个prototype原型都有一个constructor属性,指向它关联的构造函数。
4. 原型链
获取对象属性时,如果对象本身没有这个属性,那就会去他的原型_ _proto_ _上去找,
如果还查不到,就去找原型的原型,一直找到最顶层(Object.prototype)为止。
Object.prototype对象也有_ _proto_ _属性值为null。
继承:
1、原型链的继承:
可以继承原型链上的属性和方法,可以继承实例的属性和方法
但实例化子类的时候,没法将参数传给父类
2、伪造对象继承:
call apply bind 直接把this指向另一个实例
可以继承构造函数内的属性和方法
可以传参数
但是不能继承原型上的属性和方法
3、组合继承:
4、类继承:
class web extends People {
constructor(name,age){
super(name,age)
}
}
let c=new web('ag',00)
console.log(c);
console.log(c.eat());
Ts
什么是ts?
ts就是 添加了 类型系统的 js ;适用于任何 规模
js的超集
两个特性:
1. 类型系统 (typescript的核心特性)
2. 适用于 任何的规模
语言: 编译型的 和 解释型的
js 解释型的语言
静态类型语言 (编译的时候已经确定了 类型) 和 动态类型语言 (运行时才会检查类型)
js-- 动态的 ts -- 静态的
强类型的语言 和 弱类型的语言 (以是否可以进行 隐式转换;可以进行隐式转换--弱类型 )
js ---- 解释型的 动态类型 弱类型的语言
ts ---- 编译型的 静态类型 弱类型的语言
安装 ts :
命令: npm install -g typescript // 全局 安装 ts
验证是否安装 成功 : tsc -v // 如果输出版本号;证明安装成功了
ts编译
tsc 文件.ts --- 编译该 ts 为 js
1. 建一个文件夹
2. 命令行 工具 打开 该文件夹 // cd 文件夹路径
3. 执行命令: tsc --init // 初始化 tsconfig.json 文件
4. control + shift + B
Ts的数据类型
let 变量名:数据类型 = 值
数字,字符串, 布尔值 undefined null 在ts中,可以使用 null 和 undefined 来定义 原始的数据类型
void 空类型一般在函数后面 any任意类型
array 数组 定义数组 (1)类型 + [] 方法 let arr:number[] = [1,2,3,4,5,6] (2) 数组 泛型 let arr:Array<number> = [1,2,3,4,5]
tuple 元组 类型;和数组基本一致 let arr:[boolean,number,string] = [true,1,''] push的时候不能超越 界值
enum 枚举的数据类型 把自然语言转为机器语言
enum weekDay {
zhouyi = 0,
zhouer=1,
zhousan=2,
zhousi=3,
shouwu=4,
zhouliu=5,
zhoutian=6
}
let a:weekDay = weekDay.zhouyi
let a; 是any类型
联合类型 用 string | number | boolean
接口 ts中定义对象的或者约束 对象
语法:
interface 接口名字 {
key: value,
key1:value1
}
定义用户接口 IUser {
name:用户姓名,必须是字符串
age: 用户年纪,必须是 数字类型
}
可选属性就是在接口变量后上加一个? //tel?: number
表示可填可不填 但不能是约束以外的属性
任意属性:语法 [prop:string]: any
规定 其他类型必须是 任意类型的子类型
只读属性 在 接口变量 前 添加 readonly
约束的是 第一次 给 对象 赋值的时候
而不是 第一次 给 只读 属性 赋值的时候