13.ES6-语法解析-let-const等
创建类继承自内置类
class HYArray extends Array {
firstItem() {
return this[0]
}
lastItem() {
return this[this.length-1]
}
}
var arr = new HYArray(1, 2, 3)
console.log(arr.firstItem())
console.log(arr.lastItem())
类的混入mixin【缘于JS只能单继承】
class Person{ }
class Runner{
running() { }
}
// 在JS中类只能有一个父类:单继承 【虽然,下面这样写没报错】
class Student extends Person, Runner { }
类的混入示例:
class Person{ }
function mixinRunner(BaseClass) {
class NewClass extends BaseClass {
running() {
console.log("running~")
}
}
return NewClass
}
function mixinEater(BaseClass) {
//直接返回一个匿名类也行
return class extends BaseClass {
eating() {
console.log("eating~")
}
}
}
//在JS中类只能有一个父类:单继承
class Student extends Person { }
// var NewStudent = mixinRunner(Student)
var NewStudent = mixinEater(mixinRunner(Student))
var ns = new NewStudent()
ns.running()
ns.eating()
//上面中,如果想混入一些属性 或 在构造函数中传入一些参数,就并不是特别好做了。
//所以用上面实现混入效果不是特别多,了解即可
【题外话】
react开发更加接近于原生js开发;react更加灵活(双刃剑)
vue是打包好的,比如:
export default {
options { … },
setup({更多函数的使用})
}
00:32:00
在react中的高阶组件【connect() 用到了很多技巧,也用到了混入】
class TopBanner extends Component { }
redux(状态) -> vuex
//柯里化函数
connect(props, dispatch)(TopBanner) 这里面有 return如下:
return class EnhanceComponent extends Component {
render() {
return<TopBanner props dispatch>
}
}
export default connect(props, dispatch)(TopBanenr)
记忆力:神经元连接越紧密,记忆可能会越深刻!
00:52:00
JavaScript有多态吗?
· 维基百科对多态的定义:多态(英语:polymorphism)指为不同数据类型的实体提供统一的接口,或使用一个单一的符号来表示多个不同的类型。
· 非常的抽象,个人的总结:不同的数据类型进行同一个操作,表现出不同的行为,就是多态的体现。
传统面向对象多态.ts 代码如下:
// Shape形状
class Shape {
getArea() {}
}
class Rectangle extends Shape {
}
class Circle extends Shape {
}
var r = new Rectangle()
var c = new Circle()
function calcArea(shape: Shape) {
console.log(shape.getArea())
}
calcArea(r)
calcArea(c)
上面这样写,是没有多态的。因为都是调用 Shape 类中的 getArea方法。
需要修改一下上面代码如下,就可形成多态:
class Rectangle extends Shape {
getArea() {
return 100
}
}
class Circle extends Shape {
getArea() {
return 200
}
}
// 传统的面向对象多态是有三个前提:
// 1>必须有继承(是多态的前提)
// 2>必须有重写(子类重写父类的方法)
// 3>必须有父类引用指向子类对象
var shape: Shap = new Rectangle0
父类的引用 子类的对象
指向->
01:05:00
JS面向对象多态.js 代码如下【符合维基百科多态的定义】:
function calcArea(foo) {
console.log(foo.getArea())
}
var obj1 = {
name: "why",
getArea: function() {
return 1000
}
}
class Person {
getArea() {
return 100
}
}
var p = new Person()
calcArea(obj1)
calcArea(p)
//下面也是多态的体现
function sum(m, n) {
return m+n
}
sum(20, 30)
sum("abc", "cba")
01:12:00
ES6 对象字面量增强的写法:
var name = "why"
var age = 18
var obj = {
// 1.property shorthand(属性的简写)
name,
age,
// 2.method shorthand(方法的简写)
foo: function() {
console.log(this)
},
bar() { //上面 foo: 这种写法的语法糖
console.log(this)
},
baz: () =>{ //给它绑定箭头函数,箭头函数不绑定this,取上层作用域
console.log(this)
},
// 3.computed property name(计算属性名)
[name + 123]: 'hehehehe'
}
obj.baz() //window对象
obj.bar() //obj对象
obj.foo() //obj对象
// obj[name +123] ="hahaha" //以前是这样添加属性名 why123,现在可以用上上面的
console.log(obj)
ES6中新增了一个从数组或对象中方便获取数据的方法,称之为解构Destructuring。
var names = ["abc","cba","nba"]
// var item1 = names[0]
// var item2 = names[1]
// var item3 = names[2]
//对数组的解构:[]
var [iteml, item2, item3] = names
console.log(iteml, item2, item3)
// 解构后面的元素
var [, , itemz] = names
console.log(itemz)
// 解构出一个元素,后面的元素放到一个新数组中
var [itemx, ...newNames] = names
console.log(itemx, newNames)
// 解构的默认值
var [itema, itemb, itemc, itemd, iteme = 'aaa'] = names
console.log(itemd) //undefined
console.log(iteme) //'aaa'
01:33:00
var obj = {
name: "why",
age: 18,
height: 1.88
}
// 对象的解构: {}
var { name, age, height} = obj
console.log(name, age, height)
var { age } = obj
console.log(age)
// 解构出来并重命名
var { name: newName } = obj
console.log(newName)
// 解构默认值
// var { address = "广州市"} = obj
// 解构重命名并赋予默认值
var { address: newAddress = "广州市"} = obj
console.log(newAddress)
解构目前在开发中使用是非常多的:
· 比如在开发中拿到一个变量时,自动对其进行解构使用;
· 比如对函数的参数进行解构;
function foo(info) {
console.log(info.name,info.age)
}
foo(obj)
// 类似上面函数,用解构来写
function bar({name, age}) {
console.log(name,age)
}
bar(obj)
01:49:00
在ES5中我们声明变量都是使用的var关键字,从ES6开始新增了两个关键字可以声明变量: let、const
· let、const在其他编程语言中都是有的,所以也并不是新鲜的关键字;
· 但是let、const确确实实给JavaScript带来一些不一样的东西;
var foo = "foo"
let bar = "bar"
// const constant(常量/衡量)
const name ="abc"
name = "cba" //报错
// 注意事项一:const本质上是传递的值不可以修改
// 但是如果传递的是一个引用类型(内存地址),可以通过引用找到对应的对象,去修改对象内部的属性,这个是可以的
const obj = {
foo: "foo"
}
obj = {} //报错
obj.foo ="aaa" //这个是可以的
console.log(obj.foo)
// 注意事项二:通过let/const定义的变量名是不可以重复定义
var foo ="abc"
var foo = "cba"
let foo = "abc"
let foo = "cba" //报错:SyntoxError: Identifier 'foo' has already been declared
var作用域提升
console.log(foo) //undefined
var foo="foo"
02:04:00
let/const作用域提升
let、const和var的另一个重要区别是作用域提升:
· 我们知道var声明的变量是会进行作用域提升的;
· 但是如果我们使用let声明的变量,在声明之前访问会报错;
【针对下面代码,从此处往下开始看】
// let/const他们是没有作用域提升
// foo被创建出来了,但是不能被访问
// 作用域提升:能提前被访问
console.log(foo) //报错:ReferenceError: Cannot access 'foo' before initialization 【foo有被创建出来,但不能被访问】
let foo = "foo"
那么是不是意味着foo变量只有在代码执行阶段才会创建的呢?
· 事实上并不是这样的,我们可以看一下ECMA262对let和const的描述;
· 这些变量会被创建在包含他们的词法环境被实例化时,但是是不可以访问它们的,直到词法绑定被求值;
02:25:00
VO/VE/ 再次提到
VE环境,还等于现在的 window吗?有点区别了,像 let/const 声明的 会放到 variables_ 中,它是 VariableMap 类型(哈希表)。
早期的v8引擎也只指向 GO(window),因为那里还没有 let/const 这东西,当出现时,为了兼容早期的v8 也会在 window中加入 let/const 声明的变量。
但是,最新的 v8引擎的浏览器,已经在 window 中不包含 let/const 声明的变量。
02:46:00
下面这两个是不一样的【别混淆】:
// 块代码(block-code)
{
//表达式
var foo = "foo"
}
// 声明对象的字面量
var obj = {
name: "why"
}
// ES5中没有块级作用域【所以,下面这样外面的 { } 形同虚设】
// 块代码(block-code)
{
//表达式
var foo = "foo"
}
console.log(foo)
在ES5中只有两个东西会形成作用域【里面能访问外面的,外面不能访问里面的】
1.全局作用域
2.函数作用域
// ES6的代码块级作用域,对var无效
// 对let/const/function/class声明的类型是有效
{
let foo = "why"
function demo() {} //function比较特殊
class Person {}
}
console.log(foo) //报错
// 不同的浏览器有不同实现的(大部分浏览器为了兼容以前的代码,让function是没有块级作用域)
demo() //不会报错
var p = new Person() //报错
if/switch/for 语句也是块级作用域,同样对 var 无效。
for(var i=0; i<10; i++) {
//(……) 这边的 i 相当于是在 { …… } 中声明的
}
假设页面上有4个按钮
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
const btns = document.getElementsByTagName('button')
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
console.log("第"+ i+"个按钮被点击")
}
}
console.log(i)
则这样,打印4;
且每个按钮点击时也是打印:第4个按钮被点击
为什么这样呢?因为这样的块级作用域,对 var 无效,访问到最外层的 i 时,已经是计算完成了的 i = 4。
以前是怎么解决呢?如下:弄个“立即执行函数”,里面写成这样:
(function(n) {
btns[i].onclick = function() {
console.log("第"+ n+"个按钮被点击")
}
})(i)
这也相当于是一个闭包,用function形成作用域,var 变量作用域起作用。
【现在的,只需要把上上面的 var i = 0; 改成 let 声明即可解决(改成 const 会报错的),让 i 形成一个块级作用域】
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
console.log("第"+ i+"个按钮被点击")
}
}
console.log(i) //报错
【现在的,i 去找上层作用域,因为 let 这个变量是有块级作用域的,那么在访问 i 的时候,实际是访问块级作用域的 let i = 0;
而这个 i 在第一次的时候是 0 的,第二次是为 1 的,…… 那么每次在这里绑定函数的时候,绑定到外层的 i 变量分别是 0 1 2 3 】
笔记-ES6-语法解析&spm=1001.2101.3001.5002&articleId=147187367&d=1&t=3&u=a7fd4c30c8fb4c30b1807b100e6a14a0)
1040

被折叠的 条评论
为什么被折叠?



