day10 - ES6
ES6学习
一、 ECMAScript6.0
2015.06发布的;每年6月都会发布一个版本;
代表下一代JS版本;让JS成为企业级开发语言;
已经成为常态;
思维导图:
二、变量的声明
1.let
1.let 声明的变量不存在变量提升;
2.不能重复声明;
3.不会追加到window对象身上,给window瘦身;
4.具备块级作用域特征:花括号表示代码块;
2.let与var的区别
1.let 是在代码块内有效,var 是在全局范围内有效
2.let 只能声明一次 var 可以声明多次
3.let 不存在变量提升,var 会变量提升
4.for 循环计数器很适合用 let
如下:
<script>
for (var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i);
})
}
// 输出十个 10
for (let j = 0; j < 10; j++) {
setTimeout(function(){
console.log(j);
})
}
// 输出 0123456789
</script>
3.const
1.声明常量
2.值不可改变的变量,也叫静态变量;
3.可以防止别人修改变量的值;
4.声明必须初始化,否则会报错;
5.const的本质:引用地址不能改变,变的是引用地址指向堆内存当中的属性。
代码:
<script>
const a = 200;//值不可改变的变量,也叫静态变量
// a = 300; //防止别人修改变量的值
console.log(a);//类型错误,给静态变量赋值
const result = {
code:1,
err:0,
data:[]
}
//从数据库读取一批数据到data里面
let data = [{name:'大聪明', gender:'帅哥'},{name:'大聪明', gender:'帅哥'}];
result.data = data; //const本质:引用地址不能改变,变的是引用地址指向堆内存当中的属性
console.log(result);
</script>
4.暂时性死区
若在外部用let声明一个变量,在对象内部也用let声明了同一个名称的变量,而在对象里面提前使用这个变量,那么就会报错,形成一个暂时性死区
如下;
<script>
//暂时性死区
let b = 300; //全局变量,不会追加到window身上,任何地方都可以用
{
console.log(typeof b); //自己身上有b 提前使用,报错
let b = 200;
}
</script>
5.冻结–freeze
const声明的常量是引用地址不能改变,变的是引用地址指向堆内存当中的属性,若想让它声明的常量的属性也不能改变,则可以用Object的freeze方法将它冻结,而判断一个判断对象是否冻结,则可以用isFrozen()方法,冻结返回true,没有被冻结返回false。
代码:
<script>
const obj = {};
obj.a = 100;
obj,b = 200;
console.log(obj);
//让对象属性也不可修改
let obj1 = {name:'大聪明', age:20};
let obj2 = Object.freeze(obj1);//冻结
obj2.gender = 'female';
console.log(Object);
console.log(Object.getOwnPropertyDescriptor(obj2, 'name'));
console.log(obj2);
//判断一个对象是否冻结
console.log(Object.isFrozen(obj));
console.log(Object.isFrozen(obj1));//true
console.log(Object.isFrozen(obj2));//true
</script>
6.let-const实现数据驱动以及数据绑定(面试题)
需求:将div里面的内容:
初始化为:
然后两秒后改变姓名,性别,及年龄:
html代码:
<body>
<div class="mydiv">
{{name}}
</div>
<div id="app">
我叫{{name}},性别{{gender}},今年{{age}}岁了
</div>
<script src="./js/Vue.js"></script>
<script>
let app = new Vue({
el:'#app',
data:{
name:'大聪明',
gender:'帅哥',
age:20
}
});
//数据驱动以及数据绑定
setTimeout(function(){
app.data.name = '派大星';
app.data.gender = '男';
app.data.age = 18;
}, 2000);
</script>
</body>
js代码:
<script>
(function(){
function Vue({el = 'body',data = {}}) {
//获取要操作的标签
this.el = document.querySelector(el);
//得到标签内容
this.html = document.querySelector(el).innerHTML;
//得到数据
this.data = data;
//调用初始化函数
this.init();
//开启对属性的监听
this.listen();
}
//对数据进行初始化 init初始化,见名知意 不会执行
Vue.prototype.init = function() {
let deHua = /\{\{(\w+)\}\}/g;
//replace第一个参数支持正则表达式
//第二个参数支持函数,使用返回值作为替换值
let str = this.html.replace(deHua, (function($, $1){
console.log($1);
return this.data[$1];
}).bind(this));//一、可用bind改变this的指向,同时返回函数自身 二、使用一个中间变量来缓存this
this.el.innerHTML = str;
}
//监听数据改变
Vue.prototype.listen = function() {
let _this = this;
let data = this.data;
for (const p in data) {
let v = data[p];//给中间变量设置默认值
Object.defineProperty(data, p, {//设置属性的值
get:function() {
//return data[p];
return v;
},
set:function(newValue) {
console.log(newValue);
v = newValue;
//不能对对象的属性直接操作
_this.init();//重新渲染页面
}
});
}
}
//暴露一个接口
window.Vue = Vue;
})()/* 自运行函数一定要运行起来,不然里面的代码不会起作用*/
</script>
三、解构赋值
解构赋值是对赋值运算符的扩展。他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
在解构中,有下面两部分参与:
解构的源,解构赋值表达式的右边部分。
解构的目标,解构赋值表达式的左边部分。
1.数组的解构赋值:是有顺序要求的,不好用;
2.对象的解构赋值:无序的,很好用,很常用;
3.如果没有匹配到,默认值就是undefined;
4.可以设置默认值:要求必须是undefined的情况下才会使用默认值;
代码:
<script>
let {name, age, gender} = {name:'weiwei', age:20}
console.log(name);
console.log(gender);
//对象的解构赋值
let {random, max} = Math;
console.log(random());
console.log(max(1,5,-3,58));
//完整版本 第一个a是匹配模式,第二个a是匹配到的值,值放到这个变量里面
let {a:a,b:b} = {a:1,b:2};
console.log(b);
//如果没有匹配到值,默认值是undefined
let {width,height, color} = {color:'red', width:'200px'}
console.log(width,height, color);
</script>
四、数字的扩展
Undefined、null、string、number、boolean、object、array、function、bigint
bigint数据类型
在数字后面加n表示bigint的数据类型
如下:
let x = 100n; //在数字后面加n表示bigint的数据类型
console.log(typeof x);
练习如下:
<script>
//二进制
let n = 0b11011;
console.log(n);
//八进制
let m = 0o701;
console.log(m);
//16进制
let i = 0xacde456
console.log(i);
//bigint 数据类型
let x = 100n; //在数字后面加n表示bigint的数据类型
console.log(typeof x);
let str = '100.45abc';
console.log(Number.parseInt(str));//100
console.log(Number.parseFloat(str));//100.45
console.log(Number.isFinite(Infinity));//false, 无限的
console.log(Number.isFinite(500));
let j = -10.999;
console.log(Math.trunc(j)); //trunc 取整,只要整数部分
console.log(Math.sign(-100));//小于0 返回-1
console.log(Math.sign(100));//大于0 返回1
console.log(Math.sign(0));//0
console.log(Math.sign(-0));//-0
</script>
五、函数的扩展
默认参数
如果要给形参设置默认值,需要把设置默认值的形参放在最后,也就是说,我们应该给尾参数设置默认值;
注:设置了默认值的形参不计入length属性;rest用于接收多余的实参,不计入length属性;
‘use strict’ 开启严格模式;
代码:
<script>
'use strict';//开启严格模式
function sum(...abc) {
//b = 100
console.log(abc);
return 1;
}
//rest: 用于接收多余的参数
console.log(sum(2,1,4,5,6,789));
//箭头函数没有arguments, 使用rest来代替
//rest没有计入函数length,设置了默认值的形参也不计入length属性;
let fn = (...args) => console.log(args);
fn(1,2,3);
console.log(fn.length);
</script>
箭头函数
1.箭头函数提供了一种更加简洁的函数书写方式。基本语法是:参数 => 函数体
2.如果函数只有一个语句用作返回值,此时可以省略大括号和return;更准确的去讲,我们就不应该使用return和花括号;
3.箭头函数里面没有this,里面的this是他在定义的时候就确定好的;
4.箭头函数不能作为构造函数使用,因为他没有自己的this,箭头函数的this是在定义的时候生效的;
5.当箭头函数要返回对象的时候,为了区分于代码块,要用 () 将对象包裹起来,如下:
<script>
// 报错
var f = (id,name) => {id: id, name: name};
f(6,2); // SyntaxError: Unexpected token :
// 不报错
var f = (id,name) => ({id: id, name: name});
f(6,2); // {id: 6, name: 2}
</script>
6.注意点:没有 this、super、arguments 和 new.target 绑定。
7.箭头函数体中的 this 对象,是定义函数时的对象,而不是使用函数时的对象。
通用:This指向的是距离他最近的function声明的函数的调用者,如果没有找到function声明的函数,那么this就找到顶层对象window;
this指向练习代码:
<script>
//1
function f() {
console.log(this);
}
window.f();
//2
let obj = {
a:1,
f: function() {
console.log(this.a);
}
};
obj.f();//obj
let f1 = obj.f;
f1();//window
//3
let obj3 = {
a:3,
f:function () {
console.log(this.a);
let a = 5;
return () => console.log(this.a);
}
}
let f3 =obj3.f();//返回箭头函数
f3();
let f4 = obj3.f;
f4()();
//4
var a = 500;
let obj4 = {
a:4,
f:function(){
console.log(this.a);
let a = 6;
return {
a:7,
f:()=>console.log(this.a)
};
}
};
let obj41 = obj4.f();
obj41.f();
let obj4f = obj4.f;
obj4f().f();
</script>