直接量和变量
直接量:数值 布尔 字符串 null undefined 对象和函数
对象是存储数据的一个容器,函数就是应用程序处理某一个系列逻辑的过程设计
null 表示也有值
undefined 表示变量未定义
变量:就是指向了某个直接量或者其他变量的‘钥匙’;
对象数据类型:
js中的数据可以分为两类,原生数据类型和对象数据类型。所谓对象数据类型,是一种复合型的数据类型,它可以把多个数据放在一起。原生数据类型,比如数值型 浮点型 布尔型等都只能存放一些直接量,也就是说单一的数据
对象:
var container={};
创建对象最常用的方式,创建对象以后,就相当于开辟了一块内存,对象中数据是以键值对的形式存在,称为对象的属性,键和值之间使用:隔开,多个数据之间使用,隔开,键就是属性名称,值就是属性值。
对象访问其中的属性使用.,访问一个不存在的属性,结果是undefined(不存在的属性,因此它是未定义的)
对象的取值:
对象不仅可以用点号(.)访问它的一个属性,也可以用中括号([])。如果用中括号,里面就允许再写一个变量。当然了,写字符串也是可以的。
如果事先属性的名称未知,或者调用的属性是动态变化的,就不能使用点号了,使用中括号可以最大程度地提升对象调用属性的灵活度。
for循环和while循环
for(var i=0; i<10;i++){}
var i=0;的意思是定义了一个变量i,第二句是i<10,表示进入循环体的条件。({})循环体中的代码是需要被多次执行的。第三句:i++是要在循环体执行完之后才会被执行。
for(语句1,;语句2;语句3){被执行的代码块}
语句1 在循环开始前执行
语句2 定义运行循环的条件
语句3 在循环已被执行之后执行
while(条件){需要执行的代码}
对象内容的遍历 for in
js运算符
= 赋值运算符
+ - * /加减乘除运算符
++ -- 自增 自减运算符
% 取余运算符
var a = 1; //定义变量a的值是1,
var b; //变量b未赋值,undefined
var sum = (b = a+++--a) + a-- + b++;
先执行(b=a+++--a),结果b=2; a++ a先参与运算再自增1,第一步得到1,1+--a ,执行--a,这时a=2;--a自减1再运算--a的结果为1 b=1+1
a-- ,此时a=1; 先运算 1+;b++ 此时b=2,b++ 先运算
sum==(b=1+1)+1+b 结果是5 ,此时a=0; b=3
数组:
数组是一个非常灵活的类型。就是一个容器,可以存放一个或者多个对象。
数组有4中定义方式;
1 直接量定义数组
var arr=[1,2,3,4];
2 构造函数的方式
var arr=new Array();//创建一个长度为0的空数组
在js中,每个类型其实都是一个函数作为支撑,Array也叫作构造函数。与第二种方法也是采用构造函数创建一个数组对象。
3 var b=new Array(8); //创建一个长度为8的数组,为8个空元素,但是依然占据内存空间
4 var c=new Array('first','second','third');//创建一个长度为3的数组,并赋与初始值
数组只有个属性,length。表示数组所占内存空间的数目,而不仅仅是数组中元素的个数。
数组的方法:
push 可以把一个元素添加到数组里面
pop splice 删除数组元素
pop 删除数组尾部的元素,先进入的元素后删除,后进入的元素先删除
splice 插入 删除 或者替换数组元素,它不仅会在原有的数组上进行修改,还会返回被处理的内容,
splice(开始位置,删除元素的个数,插入部分)
join 把数组中的所有元素放入一个字符串。元素是通过指定的分隔符进行分割的,join(分隔符)
函数
函数定义
需要使用关键字 function
function a(){}
var a=function(){} 变量名就是函数名
js代码在运行之前会经过一个编译过程,分为3个步骤。
分词 js代码其实激素hi由一句句话组成的,分词的目的是把这些代码分解为一个个有意义的代码块;
解析 由js编译器对刚才分词得到的一个个代码块进行解析,生成一棵抽象的语法树。js代码是没有办法直接运行的,要运行js代码,就需要通过js编译器对其进行编译,只有编译之后的代码才可以被识别,然后通过js引擎执行代码逻辑。由于js这门编程语言的特殊性,其编译的过程一般就在代码执行前的几微妙甚至更短的时间之内。所以直观看,编译和运行是同时发生的,或者说我们根本感觉不到编译的存在。
抽象语法树定义了代码本身,通过操作这棵树可以精准地定位到赋值语句、声明语句和运算语句。
作用域
js中只有函数作用域和全局作用域
参数传递
任何一个变量在被赋予真正的值之前,其在编译阶段都是undefined。函数的参数可以被理解为一种预备变量,可以这样说,任何变量在被赋予真正的值之前,其在比编译阶段都是undefined。
arguments
闭包
function test(){
var a=100;
return function(){
console.log(a)
}
}
产生闭包的条件,
1 在函数内部也有一个函数, 返回的匿名函数
2 函数内部的函数用到了外部函数的局部变量。匿名函数使用到了外部函数定义的局部变量a
3 外部函数把内部函数作为返回值reutrn出去 匿名函数被reuturn 出去
好处:
正常情况下,我们调用一个函数,其里面的局部变量会在函数调用结束后销毁,这也是我们在全局作用域中无法访问函数局部变量的原因。但是,如果你使用了闭包,那么就会让这个局部变量不随着原函数的销毁而销毁,而是继续存在。闭包里面可以访问外部函数中局部变量,这种变量销毁,需要手动赋值null,js会走动扫描函数中值为null的变量,一旦找到就会自动清除这些无用的变量。
自执行函数
很多时候,我们只想执行一个函数,却无所谓这个函数叫什么名字。那么在这种情况下,就可以考虑使用自执行函数了。
语法:
(定义一个没有名字的函数)();
(
function(){
console.log(123);
}
)();
自执行函数经常和函数闭包一起使用
上面的例子可以改写成:
function test(){
var a=1;
return (function(){
console.log(a);
})();
}
new 一个函数
this永远指向当前函数的调用者,this一旦出现就一定出现在函数中,this指向函数的调用者,这个函数是谁调用的,那么this就是谁
js中分为全局作用域和函数作用域,在全局作用域中顶底的任何东西,不管是一个变量还是一个函数,其实都是window对象的。
如果调用函数的时候使用了new关键字,在函数内部就会产生一个新的对象,也就是函数的真实调用者,this关键字指向的那个对象,然后函数默认返回了这个新的对象。这种函数叫做构造函数,通过这种方式,我可以通过构造函数构建一个对象模板。
function test(){console.log(this)}
var newObject=new test();
newObject就是函数里面的this
对象模板就是指用一个函数的形式设计一种对象的种类。
因为函数在适用new 关键字以后会从内部新产生一个对象出来,而this就指向了这个对象。
回调函数
回调函数就是指把一个函数的定义当作参数传递给另一个函数。
函数作为参数
精度
0.1+0.2=0.30000004
精度丢失问题 不仅是加减法 小数乘除法的计算依然会有精度丢失的问题
解决办法:化浮为整
小数的计算会丢失精度,整数的计算没有这个问题,可以先把小数化为整数进行计算,再除以一个共同的倍数
//js小数的加减乘除都有精度丢失的问题,整数没有你这样得问题
function add(num1,num2){ num1=num1.toString();num2=num2.toString();//转为字符串 let ws1=0,ws2=0;//获取小数点位数 ws1=num1.split('.')[1]?.length||0; ws2=num2.split('.')[1]?.length||0; num1=parseInt(num1.replace('.',''));//去掉小数点,不用数值乘以两个数的位数差值的10的幂的原因是:小数的乘法也要精度丢失的问题 num2=parseInt(num2.replace('.','')); let beishu=Math.pow(10,Math.abs(ws1-ws2)); let maxWs=ws1>ws2?ws1:ws2;//小数点位数最大值 //Math.abs(ws1-ws2),获取两个数值的位数差值, //beishu就是较小数值补齐位数需要相乘的数Math.pow(a,b)得到a的b次幂 //比较小的数,补齐位数 num1>num2?(num2=num2*beishu):(num1=num1*beishu) return (num1+num2)/Math.pow(10,maxWs) }
函数的三大要义
第一 理解返回值 参数列表 和函数体
第二 业务逻辑
第三 函数的调用
HTML超文本标记语言,功能比普通的文本更加强大,是使用一组标签对内容进行描述的语言,它不是编程语言,而是一种解释性语言,它没有逻辑顺序,只有结构。
jQuery选择器,css选择器
vue
处理事件冒泡
.stop 阻止事件冒泡
.prevent 阻止提交,form表单组件和a链接组件都会导致页面刷新和跳转。如果不希望页面刷新,则可以加上.prevent以阻止这种默认的刷新操作。 .prevnet 只对form和a标签有效。
.capture 作用是优先触发,就是优先级的调整。
.self 当仅单击元素本身时,只允许元素自己触发,子元素无法触发。
.once 只触发一次
this指向函数的调用者
setTimeout(function(){console.log(this);},20000); this出现在函数中,this指向函数的调用者,setTimeout函数是一个延时函数,属于window对象,所以this指向的是window。
在实际的代码编写过程中,每当遇到这种回调函数的情况,一定要特别小心,重点要看当前这个函数是不是Vue对象自己的函数,函数都放在methods里面的,其中也并没有一个叫做setTimeout的函数,setTImeout函数式一个延时函数,属于window对象。所以上面的代码相当于这样 window.setTimeout(function(){console.log(this);},20000);
在setTimeout中处理vue的data数据,可以在函数外面定义 let that=this;将Vue对象存起来,然后在回调函数里面调用即可;
组件component
组件的名字驼峰式的命名法,在调用组件的时候需要格外注意,每次要换成大写字母的地方都需要额外添加一个半字线(-),然后大写字母转变成小写字母
监听 watch
计算属性 computed
过滤器 filters
{{today | dateFormat}}
过滤器可以叠加使用,比如添加样式,需要使用v-html,vue 2.0开始不再支持v-html中使用过滤器了,解决办法是把过滤器当成一个普通方法进行调用。在定义的Vue对象中,所有过滤器都会被挂载在$options.filters对象上,所以我们可以直接这样写:
v-html="$options.filters.dateFilter(today)"//v-html="today|dateFilter|boxStyle"不支持这种写法
node
node就是让js也可以编写服务器的代码
npm 模块管理,模块的下载和发布
package.json
name:模块的名字
version:版本号
description:模块的描述
main:代表模块的启动文件,一些复杂的模块可能会使用到一些其他资源,但是模块的启动文件,或者说入口只能有一个。
npm允许再package.json文件里面使用scripts字段定义脚本命令。
scripts:{
'test':"echo 'this is a test'"
}
test是命令,npm run test ;echo表示在屏幕上输入一段文字。
npm 所有的穆凯都发布在http://www.npmjs.com上面,
在发布代码之前,需要在npm.js上注册一个账号,才有权限发布自定义的模块;
模块发布
npm adduser 添加用户
npm publish 发布模块
npm 安装模块
npm install 模块名
运行结果:
自定生成一个package-lock.json,在node——modules中就可以看到我们的模块了。
npm 一般运行速度比较慢,事假发开中应使用国内的服务器地址,使用cnpm
使用vue-cli搭建项目
vue-cli就是进行vue组件化开发的一个脚手架。可以理解为了一项目模板
安装vue-cli
npm install -g @vue/cli@3.0.1
-g 全局安装,安装之后,在任何地方都可以使用Vuecli脚手架了
还需要安装一个原型工具
cnpm i -g @vue/cli-service-global@3.0.1
版本号一定要一致,不然会出现一些莫名其妙的错误。
vue-cli创建的项目默认支持ES6的语法
es6: let 实现块级作用域,内部变量不会影响全局
const 定义常量 提升了js的安全性
变量的解耦赋值
作用是把获取对象中方法以及赋值给对应变量的过程一次性做完。
let {name='张三',age,sxe}=Person;
字符串升级
es6
1 允许字符串直接通过for循环的方式遍历
for(let s of str) 这里用到的是of不是in,如果是in,则获取的是每个字符对应的下标。
2 允许反引号进行一些简化的字符串定义,模板字符串 `你好,${name}`,这一改进支持了换行和变量注入。
3 字符串补全
例如:依次打印0~99,但是不足2位的数字需要用0左补齐,
for(let i=0; i<100;i++){console.log(i.toString().padStart(2,'0'))}
padStart:返回新的字符串,表示用参数字符串从头部(左侧)补全原字符串
padEnd:返回新的字符串,表示用参数字符串从尾部(右侧)补全原字符串
第一个参数:生成字符串的最小长度,第二个参数:用来补全字符串,默认是空格;
字符串允许被当做数组一样使用,你可以用下标的方式获取字符串中某个位置的字符。
Proxy 代理
在支持Proxy的浏览器环境中,Proxy(target,handler)是一个全局对象,它可以被直接使用。Proxy是一个构造函数,target是被代理的对象,handler是声明了各类代理操作的对象,最终返回一个代理对象。外界每次通过代理对象访问taregt对象的属性时,就会经过handler对象,从这个流程来看,代理独享很类似middleware(中间件)。那么Proxy可以拦截什么操作呢?最常见的即使get set 对象属性等操作。
Proxy的作用就是允许我们声明一个代理,对某个对象进行一些特殊的访问拦截。一个Proxy对象由两个部分组成:target handler。在通过Proxy构造函数生成实例对象时,需要提供者两个参数。target即目标对象,handler是一个对象,声明了代理target的指定行为。
强化后的数组
快速构建新数组
Array.of将参数中的所有制最为元素而形成数组
Array.from 可以将类数组或可迭代对象转化为数组,类数组对象就是一种可以遍历的对象,只要对象由length属性,就可以被称为类数组,可以接收第二个参数,就是一个map的回调函数,用于对每个元素进行处理,放入数组的就是处理后的元素。
find
findIndex
fill 将一定范围索引的数组元素内容填充为单个指定的值
copyWithin 将一定范围索引的数组元素修改为此数组另一指定范围索引的元素
entries
keys
values
数组复制
...
强化后的函数
箭头函数 允许省略function关键字,直接用一个箭头声明一个函数
箭头函数中的this对象是定义函数时的对象,而不是使用函数时的对象。一个小窍门:只要使用了箭头函数,就不管这个函数本身了,在外面寻找最近的大括号,然后看这个大括号处在怎么样的环境中,this就指向它。
let Person={
name:'zahngsan',
getName:()=>{
return this.name
},
getName1:function(){return this.name},
sayHi:function(){
setTimeout(()=>{console.log(this.name)},3000);
},
sayHi1:function(){
setTimeout(function(){console.log(this.name)},3000);
},
sayHi2:()=>{
setTimeout(function(){console.log(this.name)},3000);
},
sayHi3:()=>{
setTimeout(()=>{console.log(this.name)},3000);
}
};
Person.sayHi()//箭头函数,找最近的大括号,就是sayHi,this就是Person对象
Person.sayHi1()//不是箭头函数,setTImeout是window的方法,this就是window
Person.sayHi2()//不是箭头函数,setTImeout是window的方法,this就是window
Person.sayHi3()//箭头函数,找最近的大括号,就是sayHi,sayHi也是箭头函数,继续找最近的大括号,就是window,this就是Window对象
更加灵活多变的对象
let name='zhangsan'; let obj={name:name};可以简写:let obj={name};//左右两边的名字一样
属性名称是一个变量:
let key='name'; let obj={[key]:'zhangsan'};
promise对象和async函数
promise(resolve,reject) 处理异步操作,then catch
async函数和await关键字(ES7)
async fun1(){//只有加上了async关键字的函数,内部才可以使用await关键字
let data=await getJosn();//getJson是一个Promise对象
}