本节内容:
一 、let 命令
二、const 命令
三、
四、
五、
一 、let 命令
1、 let基本特点
特点:
1.a是局部作用域的function xx(){let a = 'xxoo';} if(){let a = 'ss';}
2.不存在变量提升
3.不能重复声明(var可以重复声明变量)
4 let声明的全局变量不从属于window对象,var声明的全局变量从属于window对象。
2 、let变量的作用域
ES6新增了let
命令,用来声明变量。它的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效
{ let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1
上面代码在代码块之中,分别用let
和var
声明了两个变量。然后在代码块之外调用这两个变量,结果let
声明的变量报错,
var
声明的变量返回了正确的值。这表明,let
声明的变量只在它所在的代码块有效。
例如 :for
循环的计数器,就很合适使用let
命令。
for (let i = 0; i < 10; i++) {} console.log(i); //ReferenceError: i is not defined //计数器i只在for循环体内有效,在循环体外引用就会报错
下面的代码如果使用var
,最后输出的是10。
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10
上面代码中,变量i
是var
声明的,在全局范围内都有效。所以每一次循环,新的i
值都会覆盖旧值,导致最后输出的是最后一轮的i
的值。
如果使用let
,声明的变量仅在块级作用域内有效,最后输出的是6
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
上面代码中,变量i
是let
声明的,当前的i
只在本轮循环有效,所以每一次循环的i
其实都是一个新的变量,所以最后输出的是6。
3、不存在变量提升
在js中只有两种作用域,全局作用域和函数作用域,在ES6之前,js是没有块级作用域。
JavaScript 仅提升声明,而不提升初始化。如果你先使用的变量,再声明并初始化它,变量的值将是 undefined。
1:所有的声明都会提升到作用域的最顶上去。
2:同一个变量只会声明一次,其他的会被忽略掉。
3:函数声明的优先级高于变量申明的优先级,并且函数声明和函数定义的部分一起被提升
函数提升的例子:
catName("Chloe");// 即使在声明之前调用依然可以执行,不会报错 function catName(name) { console.log("我的猫名叫 " + name); }
let
不像var
那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。
console.log(foo); // 输出undefined console.log(bar); // 报错ReferenceError var foo = 2; let bar = 2;
上面代码中,变量foo
用var
命令声明,会发生变量提升,即脚本开始运行时,变量foo
已经存在了,但是没有值,所以会输出undefined
。
变量bar
用let
命令声明,不会发生变量提升。这表示在声明它之前,变量bar
是不存在的,这时如果用到它,就会抛出一个错误
在定义的函数名字和变量名相同的情况下,函数提升优先级高于变量的例子
func(); // 1 var func; function func() { console.log(1); } func = function() { console.log(2); }
牢记这三点:
只有声明本身会被提升,而赋值操作不会被提升。
变量会提升到其所在函数的最上面,而不是整个程序的最上面。
函数声明会被提升,但函数表达式不会被提升。
4、不允许重复声明
let不允许在相同作用域内,重复声明同一个变量。
// 报错 function () { let a = 10; var a = 1; } // 报错 function () { let a = 10; let a = 1; }
因此,不能在函数内部重新声明参数。
function func(arg) { let arg; // 报错 } function func(arg) { { let arg; // 不报错 } }
5、let声明的全局变量
ES5声明变量只有两种方式:var和function。
ES6有let、const、import、class再加上ES5的var、function共有六种声明变量的方式。
还需要了解顶层对象:浏览器环境中顶层对象是window.
ES5中,顶层对象的属性等价于全局变量。var a = 10; window.a
ES6中,有所改变:var、function声明的全局变量,依然是顶层对象的属性;let、const、class声明的全局变量不属于顶层对象的属性,
也就是说ES6开始,全局变量和顶层对象的属性开始分离、脱钩,目的是以防声明的全局变量将window对象的属性造成污染,
因为window对象是顶层对象,它里面的属性是各个js程序中都可以使用的,不利于模块化开发,
并且window对象有很多的自有属性,也为了防止对window的自由属性的污染,所以在ES6中将顶层对象和全局变量进行隔离。
var a = 1; console.info(window.a); // 2 let b = 2; console.info(window.b); //undefined
二 、const 命令
1、基本特点
基本上和let一致,只有const是不可改变的量
特点: 1.局部作用域
2.不存在变量提升
3.不能重复声明
4.一般声明不可变的量
三 、
1、ES5函数的写法
//ES5写法 function add(x){ return x }
add(5); //匿名函数 var add = function (x) { return x }; add(5);
2、ES6函数的写法
//ES6的匿名函数 let add = function (x) { return x }; add(5); //ES6的箭头函数,就是上面方法的简写形式 let add = (x) => { return x }; console.log(add(20)); //更简单的写法,但不是很易阅读 let add = x => x; console.log(add(5)); 多个参数的时候必须加括号,函数返回值还是只能有一个,没有参数的,必须写一个() let add = (x,y) => x+y;
四、
定义:js中自定义对象相当于Python中的字典
1、this的指向问题
$(xx).click(function(){ this -- 绑定事件的DOM标签对象 })
document.getElementById('d1').onclick = function(){this.innerText;};
2、es5对象中封装函数的方法
1、匿名函数的this指向
var name = '子俊'; var person1 = { name:'超', age:18, f1:function () { //在自定义的对象中放函数的方法 console.log(this);//this指向的是当前的对象,{name: "超", age: 18, f1: ƒ} console.log(this.name) // '超' } }; person1.f1(); //通过自定对象来使用函数,谁调用this就指向谁
2、箭头函数的this指向
var name = '子俊'; var person1 = { name:'超', age:18, f1:() => { //在自定义的对象中放函数的方法 console.log(this); //this指向的不再是当前的对象了,而是指向了person1的父级对象(称为上下文),而此时的父级对象是我们的window对象,Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} console.log(this.name) // '子俊' } }; person1.f1();
3、es6对象中封装函数的方法
1、匿名函数的this指向
let name = '子俊'; let person1 = { name:'超', age:18,
f1:function () { //在自定义的对象中放函数的方法 console.log(this);//this指向的是当前的对象,{name: "超", age: 18, f1: ƒ} console.log(this.name) // '超' } }; person1.f1(); //通过自定对象来使用函数
2、箭头函数的this指向
let name1 = '子俊'; let person1 = { name1:'超', age:18, f1: () => { //在自定义的对象中放函数的方法 console.log(this);//this指向的不再是当前的对象了,而是指向了person的父级对象(称为上下文),而此时的父级对象是我们的window对象,Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} console.log(this.name1) // 'undefined' // 由于外层的name1 不属于window对象 } }; person1.f1();
3. 函数写法的单体模式
let name = '子俊'; let person1 = { name:'超', age:18, //可以写成 f1(){} 相当于 f1:function(){} f1:function () { //在自定义的对象中放函数的方法 console.log(this);//this指向的是当前的对象,{name: "超", age: 18, f1: ƒ} console.log(this.name) // '超' } }; person1.f1(); //通过自定对象来使用函数
五、
1、
<script> //es5写类的方式 function Person(name,age) { //封装属性 this.name = name; //this--Python的self this.age = age; } //在类中不能封装方法 //封装方法,原型链 Person.prototype.f1 = function () { console.log(this.name);//this指的是Person对象, 结果:'超' }; //封装方法,箭头函数的形式写匿名函数 Person.prototype.f2 = ()=>{ console.log(this); //Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} this指向的是window对象 }; var p1 = new Person('超',18); p1.age p1.f1(); p1.f2(); //其实在es5我们将js的基本语法的时候,没有将类的继承,但是也是可以继承的,还记得吗,那么你想,继承之后,我们是不是可以通过子类实例化的对象调用父类的方法啊,当然是可以的,知道一下就行了,我们下面来看看es6里面的类怎么写 </script>
2、
<script> class Person2{ constructor(name,age){ //对象里面的单体模式,记得上面将函数的时候的单体模式吗,这个方法类似于python的__init__()构造方法,写参数的时候也可以写关键字参数 constructor(name='超2',age=18) //封装属性 this.name = name; this.age = age; } //注意这里不能写逗号 showname(){ //封装方法 console.log(this.name); } //不能写逗号 showage(){ console.log(this.age); } } let p2 = new Person2('超2',18); p2.showname() //调用方法 '超2' //es6的类也是可以继承的,这里咱们就不做细讲了,将来你需要的时候,就去学一下吧,哈哈,我记得是用的extends和super </script>