2020/02/08 04-JS新旧类构造、静态方法和this的问题

在这里插入图片描述
JS对象模型是个难点,跟其他语言都不一样,是基于对象的,基于原型(prototype)的面向对象语言,而不是基于类的面向对象语言。

C++和JAVA是有类class和实例instance的概念,抽象东西需要具象化,实例是类的实体
在这里插入图片描述
JS是基于原型的,只有原型对象的概念,原型对象就是一个个模版,新的对象从这个模版构建从而获得最初的属性。任何对象在运行时都可以动态增加属性(跟python一致),任何一个对象都可以作为另一个对象的原型,这样后者就可以共享前者的属性。
在这里插入图片描述
在这里插入图片描述
类的申明方式,可以是标识符,数字,字符串,都可以作为key
在这里插入图片描述在这里插入图片描述a是标识符的写法,最后也转换成了string
在这里插入图片描述
1也变成了string,属性最后都是string
在这里插入图片描述
这种定义的方式,最后都要转换成字符串的方式
在这里插入图片描述在这里插入图片描述
还有一种定义方式,是借用函数来实现的,ES6之前的定义方式,这样定义的类,借用函数的方式,这个this跟python里的self是同一个意思,实例自身

在这里插入图片描述
这里面是可以写函数的
在这里插入图片描述
所有实例的创建要用new,不加new,使用会抛出异常,这叫普通函数调用,用的是函数返回值
在这里插入图片描述
这个函数返回值是undefined
在这里插入图片描述
A是个对象,这个对象有两个属性,x,y,所以应该加new,没有传值,所以两个都是undefined
在这里插入图片描述
给两个值就成了,4,5,这是ES6之前的类定义方式,要当成类来用,就用new
在这里插入图片描述
打印a其实和this一样,this就是指向当前实例,this就是self
在这里插入图片描述
在C++和JAVA中,称为this指针
在这里插入图片描述
去掉new试试,a打印之前,先要经过第16行,就需要先做函数调用,就需要先执行
在这里插入图片描述
后面有xy,也就是4,5真的动态注入到某个对象上了
在这里插入图片描述
普通函数调用,这个this就是全局对象
在这里插入图片描述
一旦new,this就不是全局对象,用了new,指向的是当前实例本身,用new相当于创建新的实例,(普通函数调用,this指向的是全局对象)
在这里插入图片描述在这里插入图片描述
称这个是构造器,是用来构造的,用new就可以构造一个实例出来,所以习惯上称为构造器,或是构造函数在这里插入图片描述
也可以有方法,这个属性只要对应到函数上就可以了
在这里插入图片描述
在18行打印了,才会有show属性
在这里插入图片描述
1的时候show还没有动态加入
在这里插入图片描述
传统方式就是用构造器,但是不能使用普通函数调用,虽然可以执行,但是会报问题,如果要作为类来用,必须使用new关键字来获得一个实例,这时候在函数体里出现的this就指向当前实例本身,就动态增加了,x,y,show这样的属性即可

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
试试能不能继承
在这里插入图片描述
这样执行看看,这些都是全局的。this出问题了
在这里插入图片描述
缺一个函数,call,(将python的super之前,类名有,要传self)需要借助call方法,call代表用这个this解决问题,这就是继承
在这里插入图片描述
这是P3D对应的对象信息
在这里插入图片描述
这是ES6之前的写法,目前还有很多人写
在这里插入图片描述
因为function是没有继承和扩展的关键字的,也不能加列表,就只能用这种方式来调用,在ES6之前需要用这种方法
在这里插入图片描述
有了call,this指定就绑定在当前实例point3D(python也是借助父类的构造器构造自己),子类该覆盖覆盖,父类就可以被子类的同名覆盖
在这里插入图片描述
虽然是基于原型的,但是面向对象还是基本保留的
使用new之后,就可以用function来构造对象,这些function称为构造函数或者构造器,每个函数,都是函数对象,都可以调用内建的call方法,将内建的这些方法传入进去
在这里插入图片描述
new关键字不用,就是一次普通的函数调用,this代表全局
在这里插入图片描述
能否改成新的方式
在这里插入图片描述
ES6开始提供了class,构造器关键字constructor,相当于python中的init,对照着改
在这里插入图片描述
可以看看Point的真面目,class只不过是一个语法糖,本质上还是以前的function,只不过新语法内部也需要使用新语法
在这里插入图片描述
对于类来讲没有什么私有属性,不跟python一样,python里的私有属性就是改名,实际上就是公开的,只不过改了名

看下下面如何写继承,新语法更像面向对象

在这里插入图片描述
point 3D里面 ,xyz都有
在这里插入图片描述
新语法可能有些浏览器跑不起来
在这里插入图片描述
这只是一种语法糖,本质上还是function,建议写ES6,constructor类似init
在这里插入图片描述
不用new也是不行的
在这里插入图片描述
使用new,就阻止你发生错误
在这里插入图片描述
ES6中的class,没有私有的属性,继承是哟个extends关键字,
一个类只能拥有一个名为constructor的构造器方法。如果没有显示的定义一个构造方法,则会添加一个默认的constructor方法。
一个构造器可以使用super关键字来调用一个弗雷的构造函数。
本质上是语法糖,可以创建起来更加简单,清晰,还是一个本质的特殊的函数。

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
构造器只能有一个
在这里插入图片描述
继承用extends,调用的时候用super
在这里插入图片描述
在这里插入图片描述
子类中直接重写父类的方法可以,可以当方法用
在这里插入图片描述
现在打印的是第6行,就是show的时候到底用了谁
在这里插入图片描述
下面这种是不同的定义方式在这里插入图片描述
现在调用就出了问题,但是可以看到属性里的变化,show:1100,属性是占优的,所以只是借了父类的构造器来构造你自己,this还是你自己,属性还是你自己的,属性优先
在这里插入图片描述
属性优先,这样下面调用起来就是上面的在这里插入图片描述
把下面的去掉,去调用,就还是1100
在这里插入图片描述
属性是优先的
在这里插入图片描述
同样的方法,子类就可以覆盖父类的
在这里插入图片描述
但是交叉的方式就出问题了,用箭头的方式也是可以的

在这里插入图片描述在这里插入图片描述
是优先使用子类的属性,如果同名的属性和方法都在,优先使用属性,子类属性覆盖父类属性
在这里插入图片描述
父类,子类使用同一种方式类定义属性或者方法,子类覆盖父类。访问同名属性或方法时,优先使用属性。
在这里插入图片描述
对于类来讲,是有静态属性的,静态属性还处于实验性的阶段
在这里插入图片描述
所谓的静态其实就是类的类属性,类的就属于全部实例的,类的需要static,实例的就是this
在这里插入图片描述
这种写法在这种语言里是错误的写法,有类不一定有实例
在这里插入图片描述
静态就是类的,拿类来调用没有问题
在这里插入图片描述
new是实例化,不放心可以在外面套一层括号,告诉你不能调用,类的就是类的,不能用实例来调用
在这里插入图片描述
所以静态的只能用类来调用,不能用实例来调用
在这里插入图片描述
跟java一样,静态就是类,类的就是类的,实例不能用,跟python的(static method不一样)

有些版本不支持静态属性在这里插入图片描述
除了python,其他C++,java,JS面向对象的语言里,静态就是类的,用类来调用即可
在这里插入图片描述
这个this肯定不是你的实例,add.print,实例不能直接访问静态方法,跟C++,JAVA一致
在这里插入图片描述
实例可以通过构造器的方式访问静态方法,构造器里面其实还有很多东西
在这里插入图片描述
在这里插入图片描述
没有实例,看看打印的ths是什么,this指的是类本身,因为这是新语法,this现在不是实例
在这里插入图片描述
思考的方式是,在调用静态的时候,有可能一个实例都没有
在这里插入图片描述
静态的就是类的,类的就是类的。
注意:
静态的概念和Python的静态不同,相当于Python中的类变量。classmethod

在这里插入图片描述

this的问题

在这里插入图片描述
有两个属性,name和getNameFunc,这个函数就相当于一个方法,调用整个方法,会return一个function函数,就可以在这个函数后面调用这个函数

定义出来就直接是一个实例,这个实例有自己的属性和方法
在这里插入图片描述
这里return是一个匿名函数
在这里插入图片描述
this.name=magedu,this=school本身

在这里插入图片描述
第一个括号代表的是方法调用,第二个括号代表返回的函数调用
在这里插入图片描述
方法调用会this.name,在这里测试叫global全局,网页测试叫全局window,浏览器对象全局叫window
在这里插入图片描述
如果是普通函数调用,this指的是全局的,
在这里插入图片描述
这个返回的是一个普通函数,紧接着调用普通函数,如果普通函数用this,指向的就是全局,this。name,全局对象里现在就没有name,相当于在问全局对象有没有name属性,因为现在name是定义在school对象上的
在这里插入图片描述
这个this纯粹跟当下用什么函数有关,如果用普通函数调用,非得用this,这里就是,如果是构造器,没有用new,这时候用this也不对,所以不用new就是普通函数调用,跟这上面一个道理

这里普通函数调用,this就已经变成全局对象 了在这里插入图片描述
如果修改,可以使用that,school传进去,跑到that里
在这里插入图片描述
但是传错地方了,上面方法调用是没用
在这里插入图片描述
所以this解决不来,可以用that,解决所有隐式传参都可以这么做

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
可以用一些高级的语法,ES6开始引入了call方法

刚才用传统的继承point,是把this传入进去
在这里插入图片描述
现在这一段调用返回的是函数,JS会帮你把函数组装成方法,call方法就是其中一个,call方法对任何一个函数对象都提供,只要肯定前面是一个函数就可以调用,call方法就可以将丢失的this强行捆进去
在这里插入图片描述
这样就相当于把函数的this,强行改成school,可以认为一个函数内部有一个this(早期兼容,如果是函数调用,this指向函数对象,如果new当实例来用,this就指向实例本身,)
现在this可以改,通过外部调用call方法传进去,等于把内部的this替换掉,call(school)不但调用call方法,还把this修改了

在这里插入图片描述
都修改了,this就不等于global了,但是this.name照样 把值拿回来了
在这里插入图片描述
函数要是有多参,除了有call方法还有另外的东西,apply
在这里插入图片描述
点开看一下
在这里插入图片描述
可变参数
在这里插入图片描述
第二参数,在call方法是剩余参数,对于apply方法,第二个参数开始必须是一个数组
在这里插入图片描述
介绍apply,call方法

5拿给x,y丢了,4不知道去哪里了
在这里插入图片描述
它把this进行修改了,对于普通函数调用,会修改this
在这里插入图片描述
第一个给了this,普通函数调用
在这里插入图片描述
如果使用apply调用,现在效果一样,不但效果一样,还会把函数里的this指针重置
在这里插入图片描述
apply区别在于需要一个数组,call方法是把后面的参数往后列即可
在这里插入图片描述
apply,需要传数组,call就直接继续写参数即可
在这里插入图片描述
在这里插入图片描述
call方法和apply方法会在源码中大量出现,是以前写的,现在还有一种写法,是以后用框架来写的时候,最要用的方式,这个方法就叫bind,所有的函数都可以call,apply,bind

在这里插入图片描述
如果是apply就可以直接得到想要的结果
在这里插入图片描述
直接用bind不能得到想要的结果
在这里插入图片描述
bind并不直接执行,不像apply和call方法直接执行就帮你执行,顺带就把你要传入的对象传进去,立刻执行得到结果。bind方法是把你传入的参数,只是做this的修改,作为绑定,绑定到这个对象上并没直接执行,只是给你返回一个新的函数,然后需要再次调用。这样也可以解决this的问题

在这里插入图片描述
所以,先bind,绑定return一个新的函数回来,然后在后面加括号调用,缺什么参数补什么参数,原来几个参数,现在就是几个参数,绑定以后新的function可以覆盖原来的function。
bind是return一个新的函数回来,这个函数里面把this重新绑定你指定的对象,原理上this应该指向实例,但是this任由你修改

在这里插入图片描述

在网页里面this指针经常会变,网页里面函数调用,this是谁,是你不能确定的,所以需要强行做绑定
在这里插入图片描述
显式传入就是that方法

在这里插入图片描述
aplly和call的定义参数是你指定的,要修改或覆盖this的
在这里插入图片描述在这里插入图片描述
2009年ES5提供了bind
在这里插入图片描述
bind最后绑定,是返回一个新的函数
在这里插入图片描述在这里插入图片描述
只要是函数调用,this是谁就需要看情况了,class里,this是指向类的,this其实是在一直变化的,不可能在写代码的时候让this变来变去,就应该提前用call,apply,bind方法,把this固定下来,改成你明确知道的实例,这样减少错误

ES6引入了箭头函数

在这里插入图片描述
改成这样,能不能得到this.name
在这里插入图片描述
现在改的是,getnamefunc,不是改的里面的匿名函数在这里插入图片描述
现在把里面的改成 了匿名的箭头函数
在这里插入图片描述
this现在不等于,查看this是空对象
在这里插入图片描述
现在是老语法和新语法混着写,混着写就容易出问题

在这里插入图片描述
刚才是在这里出的问题,修改一下就搞定了,老的语法不建议加载新的箭头函数语法,箭头函数按照新的语法,解决了this绑定的问题,新的应该用class定义方式,用老语法就不要混着箭头函数了
在这里插入图片描述
建议使用call,apply,bind的方式来解决,不然一会老语法,一会新语法,别人无法修改,箭头函数已经不管原来的this绑定问题了,只要在谁的作用域,就把this绑定好了,不需要你关心了
在这里插入图片描述在这里插入图片描述
需要改造下,比如用全新的方式来写
在这里插入图片描述
getnamefunc()会返回一个箭头函数在这里插入图片描述

这样就有了

在这里插入图片描述
bind方法也是常用的方式
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值