var 升明
在函数作用域或全局作用域中通过关键字var声明的变量,无论实际上是在那里声明的,都会被当成在当前作用域顶部声明的变量,这就是我们常说的提升机制。
块级声明用于声明在指定块的作用域之外无法访问的变量。块级作用域(也叫词法作用域)存在于函数内部或(字符和{}之间的区域)
let声明的用法与var相同。用let代替var来声明变量,就可以把变量限制在当前的代码块中。
正常var 声明和 let声明的对比
//var声明
var results=true
if(results){
var cols='blue'
}
console.log(cols)//blue
//let声明后,不在被提升到顶部,执行流离开if语句之后cols会被销毁。所以是is not defined
var results=true
if(results){
let cols='blue'
}
console.log(cols)//cols is not defined
在同一个作用域中不能声明两个同名的变量
//会提升results已存在
var results=true
let results=true
如果在当前作用域中内嵌另一个作用域,便可在内嵌的作用域中用let声明同名变量
//这样不会出现错误提示
var results=true
var cols='red'
if(results){
let cols='blue'
}
使用const声明的是常量,其值一段被设定不可更改。并且每个声明的常量必须要进行初始化,如果不进行会有错误提示。
//语法错误,未初始化
const str1;
const与let声明都是块级标识符,所以常量也只在当前代码块内有效,执行到块外会被立即销毁。常量也不会被提升到作用域顶部。另外在同一作用域中声明已经存在的变量会导致语法错误(var let都会出错)
var results=true
if(results){
const cols='blue'
}
console.log(cols)//cols is not defined
const声明的变量不可在赋值,在赋值会导致语法错误
const names='张三'
names='李四'//语法错误
用const声明对象。如果是对象,对象的中的值可以修改。
//只能修改对象的值,不能修改对象的绑定。
const obj={
name:'张三'
}
obj.name='李四'
console.log(obj.name)//李四
如果在全局作用域下用var可以通过window调用,但是let和const则不行,它们会在全局作用域下添加一个新的绑定,但该绑定不会添加为全书对象的属性。换句话说用let或const不会覆盖全局变量。
let l1=1
const l2=2;
var l3=3;
console.log(window.l1)//undefined
console.log(window.l2)//undefined
console.log(window.l3)//3
总结:默认使用const,如果需要改变变量的值使用let,如果window访问或跨iframe则用var
只归纳了部分使用频率比较高的
函数中的默认参数(ES5)
function makeRquuest(url,timeout,callback){
timeout =(typeof timeout!=='undefined')?timeout:2000
callback=(typeof callback!=='undefined')?callback:function(){}
}
函数中的默认参数(ES6)
function makeRquuest(url,timeout=200,callback=function(){}){
}
不定参数
1,在函数的命名参数前添加三个点(...)就表明这是一个不定参数,该参数为一个数组,包含着自定传入之后的所有参数,通过这个数组名即可访问里面的参数。
不定参数的写法
function funs(num,...num2){
}
2,不定参数的使用限制,每个函数最多只能声明一个不定参数,而且一定要放在所有参数的最后面。不定参数不能用于对象字面段setter中
function funs(num,...num2,num3){//直接出现错误提示
}
3,不定参数对arguments的影响
不定参数代码了arguments对象。如果声明函数时使用了不定参数,则在函数被调用时,arguments对象包含了所有传入函数的参数。(不管是不是不定参数,arguments对象总是包含所有传入函数的参数)
function funs2(...nums) {
console.log(nums[0])//1
console.log(nums[1])//2
console.log(nums[2])//3
return nums[0]+nums[1];
}
console.log(funs2(1,2,3))//3
箭头函数的特别
1,没有this,super,arguments和new.target绑定,是由外围最近的一层非箭头函数决定;
2,不能通过new关键字调用(箭头函数没有construct方法,所以不能用作构造函数);
3,没有原型;
4,不可以改变this的绑定;
5,不支持arguments对象;
6,不支持重复的命名参数;
箭头函数语法
写法1
只有一个参数,可以直接写参数名,箭头跟在后面
//函数1
let fun1=value=>value;
console.log(fun1(2))//2
//函数2
let fun2=function (value) {
return value
}
console.log(fun2(3))//3
//这两个函数等价
写法2
如果需要在其中传入两个或两个以上的参数
//函数1
let sum1 =(num1,num2)=>num1+num2;
console.log(sum1(1,2))//3
//函数2
let sum2=function(n1,n2){
return n1+n2
}
console.log(sum2(1,2))//3
写法3
没有参数
//函数1
let sum1 =()=>'hh';
console.log(sum1())//hh
//函数2
let sum2=function(){
return 'hh';
}
console.log(sum2())//hh
写法3
传统函数体
//函数1
let sum1 =(num1,num2)=>{
return num1+num2
}
console.log(sum1(1,1))//2
//函数2
let sum2=function(n1,n2){
return n1+n2
}
console.log(sum2(1,1))//2
写法4
向外返回一个对象字面量
//箭头函数
let obj1=id=>({id:id,name:'张三'})
//传统函数
let obj2=function(id){
return{
id:id,
name:'张三'
}
}
1,属性初始值的简写,当一个对象的属性与本地变量同名时,不必在写冒号和值,简单地只写属性名即可。如下
//ES5的写法
function persons(name,age){
return{
name:name,
age:age
}
}
//ES6简写法
function persons(name,age){
return{
name,
age
}
}
2,对象方法的简写消除了冒号和function关键字
let obj={
name:'张三',
sayName(){
console.log(this.name)
}
}
1,对象解构(就是把数据打平的一种方式)
let node ={
name:'张三',
age:18,
}
let {name,age}=node;
console.log(name,age);//张三,18
上面这几行代码的意思是,将node.name和node.age分别存放在name和age中
2,默认值
使用解构表达式时,如果指定的局部变量名称在对象中不存在,这个局部变量就会是undefined
注意点:当指定的属性不存在时,可以随意定义一个默认值,在属性名后面加一个等号和相应的默认值即可
let node ={
name:'张三',
age:18,
}
let {name,age,height}=node
console.log(name);//张三
console.log(age);//18
console.log(height)//undefined
//当指定的属性不存在时,可以随意定义一个默认值,在属性名后面加一个等号和相应的默认值即可
let node ={
name:'张三',
age:18,
}
let {name,age,height}=node
console.log(name);//张三
console.log(age);//18
console.log(height)//180
3,为非同名变更赋值
如果不希望使用不同命名的局部变量来存储对象属性的值,可以使用下面的这种写法;
let node ={
name:'张三',
age:18,
}
let {name:n1,age:a1}=node
console.log(n1);//张三
console.log(a1);//18
这种写法与传统的对象字面量写法相反,现在变量名在右,属性名在左
当使用变更名进行赋值时也可以添加默认值,只需要在变量名和等号后添加默认值即可
let node ={
name:'张三',
age:18,
}
let {name:n1,age:a1,height:h1=180}=node
console.log(n1);//张三
console.log(a1);//18
console.log(h1)//180
4,嵌套对象解构
解构嵌套对象与对象字面量语法一样,可以将对象拆解以获取有用的信息
let node ={
name:'张三',
age:18,
address:{
home:'210',
road:'金融港',
class1:{
name:'赵二',
age:100
}
}
}
let {name,address:{road,class1}}=node
console.log(name)//张三
console.log(road)//金融港
console.log(class1.age)//100
console.log(class1.name)//赵二
使用非同名变量赋值(其实和上面一样)
let node ={
name:'张三',
age:18,
address:{
home:'210',
road:'金融港',
class1:{
name:'赵二',
age:100
}
}
}
let {name:n1,address:{road:r1,class1:{name:n11,age:a22}}}=node
console.log(n1)//张三
console.log(r1)//金融港
console.log(n11)//赵二
console.log(a22)//100
1,它使用的是数组字面量,且解构操作全部在数组内完成,
let arr1=[1,2,3,4,5,6,7,8,9,10];
//下面这行代码的意思是将1和2分别存储在变更a1和a2中
let [a1,a2]=arr1;
console.log(a1)//1
console.log(a2)//2
另一种使用方法,可以直接省略元素,为感觉兴趣的元素提供变量名如下(F2前的逗号是前方元素的点位符),可以通过这种方式取到任何想要的元素。
let arr1=[1,2,3,4,5,6,7,8,9,10];
//现在想要数字3
let [,,f2]=arr1
console.log(f2)//3
2,交换变量
let a=1,b=2;
[a,b]=[b,a];
console.log(a)//2
console.log(b)//1
3,默认值
也可以在数组解构赋值表达式中为数组中的任意位置添加默认值,当指定的值不存在或undefined时使用
let arr2=[1,2];
let [a1,a2,a3=3]=arr2;
console.log(a1)//1
console.log(a2)//2
console.log(a3)//3
4,嵌套数组解构
在原有的数组模式中插入另个数组,深入下一层
let arr2=[1,2,[4,5,[6,7]]];
let [a1,a2,[a3,a4,[a5]]]=arr2
//这里的第二个数组引用的就是4,第三个为5,依次类推
console.log(a1)//1
console.log(a2)//2
console.log(a3)//4
console.log(a4)//5
console.log(a5)//6
5,不定元素(一般使用...语法将数组中的特定元素赋值给另一个特定的变量)
//用法1
let arr2=[1,2,[4,5,[6,7]]];
let [a1,...a2]=arr2;
console.log(a1)//1
console.log(a2[0])//2
console.log(a2[1])//4,5,6,7
console.log(a2[1][0])//4
console.log(a2[1][1])//5
console.log(a2[1][2][0])//6
console.log(a2[1][2][1])//7
//用法2
let arr3=['张三','李四','王五','赵六']
let [b1,...b2]=arr3;
console.log(b1)//张三
console.log(b2[0])//李四
console.log(b2[1])//王五
console.log(b2[2])//赵六
不定元素语法还有另外一个功能,就是对数组实现复制类似于concat()方法所干的事
6,混合解构
//解构一
let arr4=[
{
name:'张三',
age:22,
height:[170]
},
{
name:'李四',
age:19
}
]
let [h1,h2]=arr4
console.log(h1.name)//张三
console.log(h1.age)//22
console.log(h1.height)//170
console.log(h2.age)//19
console.log(h2.name)//李四
//解构二
let obj4={
type:'1',
name:'la',
arr:{
str:{
a:1,
b:2
}
},
arr2:[1,2,3]
}
let {name,arr:{str},arr2:[a1,...a2]}=obj4
console.log(name)//la
console.log(str.a)//1
console.log(str.b)//2
console.log(a1)//1
console.log(a2[0])//2
console.log(a2[1])//3
es6中引入了第6种数据类型Symbol,Symbol的值是唯一不重复的
1,创建一个symbol
let firstName=Symbol();
let person={};
person[firstName]='asdf';
console.log(person[firstName])
注意:不能使用new Symbol会导致出错
2,Symbol接收一个可选参数,其可以让你添加一段文本描即将创建的Symbol,这段描述不可用于属性访问。方便阅读代码和调试。
let firstName=Symbol('青青的湖水');
let person={};
person[firstName]='asdfghjkl';
console.log('青青的湖水' in person)//fase
console.log(person[firstName])//asdfghjkl
console.log(firstName)//Symbol(青青的湖水)
3,Symbol类型检测
let sym = Symbol("javascript");
console.log(typeof sym)//symbol
ES5中的近类结构
function PersonTypeName(name){
this.name=name;
}
PersonTypeName.prototype.sayName=function(){
console.log(this.name)
}
let person = new PersonTypeName('张小飞')
person.sayName();//张小飞
console.log(person instanceof PersonTypeName)//true
console.log(person instanceof Object)//true
/*详解:PersonTypeName是一个构造函数,执行后创建一个名为name的属性;并给personTypeName的原型添加一个sayName的方法,所以personTypeName对象的所有实例都共享这个方法。然后使用new操作符创建一个personTypeName的实例person,并最终证明了person对象确实是personTypeName的实例。且由于存在原型继承的特性,因而它也是object的实例.*/
类的声明
基本的类声明
class PersonClass{
//等价于PersonTypeName
constructor(name) {
this.name=name
}
//PersonTypeName.prototype.sayName
sayName(){
console.log(this.name)
}
}
let Person2=new PersonClass('李小四');
Person2.sayName();//李小四
console.log(Person2 instanceof PersonClass);//true
console.log(Person2 instanceof Object);//true
console.log(typeof PersonClass);//function
console.log(typeof PersonClass.prototype.sayName)//function
类表达式
let PersonClass=class {
constructor(name) {
this.name=name
}
sayName(){
console.log(this.name)
}
say(){
return 'haha'
}
}
let user2=new PersonClass('name')
console.log(user2.say())//haha
console.log(user2 instanceof PersonClass)//true
console.log(user2 instanceof Object)//true
命名类表达式
let PersonClass = class PersonClass2 {
constructor(name) {
this.name=name
}
sayName(){
return this.name
}
}
console.log(typeof PersonClass)//function
console.log(typeof PersonClass2)//undefined
未完待续...