当前位置: 首页 > news >正文

建站系统哪个比较好wordpress 侧边栏左边

建站系统哪个比较好,wordpress 侧边栏左边,新手建设网站,发布信息的免费平台目录 原型隐式原型显式原型constructornew操作符 重写原型对象原型链继承原型链继承借用构造函数继承组合构造继承 原型继承寄生继承组合寄生继承 原型继承关系 原型 在JavaScript中,每个对象都有一个内置属性[[prototype]],这个属性指向一个另一个对象…

目录

  • 原型
  • 隐式原型
  • 显式原型
  • constructor
    • new操作符
  • 重写原型对象
  • 原型链
  • 继承
    • 原型链继承
    • 借用构造函数继承
      • 组合构造继承
    • 原型继承
    • 寄生继承
      • 组合寄生继承
  • 原型继承关系

原型

JavaScript中,每个对象都有一个内置属性[[prototype]],这个属性指向一个另一个对象
当我们访问对象中的属性时,会触发[[GET]]操作
这个操作会现在自己对象内部寻找对应的值,如果找不到就会在[[prototype]]中所指向的对象中寻找
可以通过__proto__Object.getPrototypeOf两个属性来访问这个对象
可以通过__proto__Object.setPrototypeOf两个属性来设置这个对象
注意,__proto__是早期浏览器自行添加的属性,而Object.getPrototypeOfObject.setPrototypeOf标准添加
如下代码所示

        var obj = {}console.log(obj.__proto__)console.log(Object.getPrototypeOf(obj))console.log(obj.__proto__ === Object.getPrototypeOf(obj))var obj2 = {}var obj3 = {a: 1}obj2.__proto__ = obj3console.log(obj2.__proto__)console.log(obj2.a)Object.setPrototypeOf(obj2, obj)console.log(obj2.__proto__)

控制台结果如下
结果

隐式原型

每个对象都会有一个__proto__属性,这个属性不建议直接访问或修改,是只在JavaScript内部使用的属性,因此被称之为隐式原型

显式原型

函数也是一个特殊的对象,是对象也就意味着也拥有隐式原型
但与普通对象不同的是,函数同时也拥有显式原型
隐式原型不同的是,显式原型可以直接访问,并且经常使用
显示原型的作用就是用来构造对象
函数的显式原型可以通过prototype属性来访问
如下代码

        function foo() {}var obj = {}console.log(foo.prototype)console.log(obj.prototype)

控制台结果如下
结果

constructor

在说明显式原型的用处之前需要先知道一个函数constructor
constructor在函数的显式原型
constructor也被称之为构造函数
这个constructor指向函数本身

        function foo() {}console.log(foo.prototype.constructor)console.log(foo === foo.prototype.constructor)

控制台结果
结果

new操作符

在之前的this绑定规则一文中new关键字做了以下操作

  1. 创建一个空对象
  2. 空对象this绑定到这个空对象
  3. 执行函数体里的代码

其实还有第四步
即将函数的显式原型赋值到空对象中的隐式原型
这意味着如果我们通过某一个函数来构建一个对象,这个对象的隐式原型指向的是函数的显式原型

        function Person() {}var obj = new Person()console.log(obj.__proto__)console.log(obj.__proto__ === Person.prototype)

控制台结果如下
结果
我们说new关键字会执行函数体里的代码,这句话不能说错
但更精确的说法是new关键字会执行显式原型中constructor函数里的代码

重写原型对象

如果我们需要在显式原型上添加许多属性,通常我们会重写整个显式原型

        function Person() {}Person.prototype = {a: 1,b: 2,foo: function () {console.log(this.a)}}var obj = new Person()console.log(obj.b)obj.foo()console.log(Person.prototype.constructor)

控制台结果如下
结果
可以看到,如果我们重写显式原型的话constructor会指向Object

        Person.prototype.constructor = Person

我们可以通过这种方式来修改Personconstructor,但这样修改得到的constructor[[Enumerable]]被设置成了true
默认情况下的constructor[[Enumerable]]false
如果想要解决这个问题,可以通过Object.defineProperty函数

        Object.defineProperty(Person.prototype, "constructor", {enumerable: false,value: Person})

这样得到的constructor就是不可枚举的了
关于对象的属性描述符可以看我这篇文章
(未动笔,未来可寄)

原型链

JavaScript中,如果要实现继承,就必须要理解一个重要概念,即原型链
当我们从一个对象获取一个属性时,如果在当前对象中没有获取到对应的值时就会通过对象的隐式原型来寻找
如果也没有找到的话就会一直向上寻找
所有对象的顶层原型为 [Object: null prototype] {}
所有通过Object创建出来的对象其隐式原型都指向这个
这个原型其实也有对应的隐式原型,但指向的是null
综上所述,在JavaScript中所有类的父类是Object
原型链的顶层对象就是Object隐式原型
在理解了原型链之后我们就能实现继承

继承

以下是几种继承的实现方式

原型链继承

原型链继承是通过JavaScript对象属性查找规则实现的一种继承方式

        function Person() {this.age = 18}var p = new Person()function Student() {this.id = "101"}Student.prototype = pvar stu = new Student()console.log(stu.age)console.log(stu.id)

控制台结果如下
结果
这个方法需要构造一个父类的实例对象,再将子类显式原型指向父类构造的实例对象子类构造实例对象时生成的对象其隐式原型就指向了父类构造的实例对象
这个方法也有自己的缺点

  1. 某些属性其实是存储在父类的实例对象上的,直接打印子类的实例对象是看不到这些属性的
  2. 这个属性会被多个对象共享
  3. 这个属性的值是唯一的

借用构造函数继承

借用构造函数继承的关键就在于子类中直接调用父类的构造函数

        function Person() {this.age = 18}function Student() {Person.call(this)this.id = "101"}var stu = new Student()console.log(stu)

控制台结果如下

结果
可以看到此时父类的属性也已经继承过来了
但这只是属性的继承,如果想要调用父类的方法的话还需要和原型链继承一起使用

组合构造继承

        function Person() {this.age = 18}Person.prototype.foo = function () {console.log(this.age)}var p = new Person()function Student() {Person.call(this)this.id = "101"}Student.prototype = pvar stu = new Student()console.log(stu.age)console.log(stu.id)stu.foo()

控制台结果如下

结果

这样我们就实现了属性和方法的一起继承
这种方法其实也有一些问题

  1. 这个方法会调用两次构造函数
    1. 一次在生成子类实例对象时调用了父类的构造函数
    2. 一次在创建子类原型的时候
  2. 所有的子类实例对象会拥有两份父类属性
    一份在自己这里,一份在自己的隐式原型中
    默认访问时优先访问自己本身有的属性

原型继承

在2006年时道格拉斯·克罗克福德提出了一种新的继承方式
这种方法并不依靠constructor来实现

        function Person() {this.age = 18}Person.prototype.foo = function () {console.log("this function")}function Student() {this.id = "101"}var obj = {}Object.setPrototypeOf(obj, Person.prototype)Student.prototype = objvar newObj = new Student()

我们使用借用构造函数继承的目的就是要一个新对象新对象隐式原型指向父类的显式原型,最后子类显式原型再指向这个新对象
通过Object.setprototypeOf方法来设置新的obj对象的隐式原型指向父类显式原型子类显式原型指向obj
这样就绕过了constructor
还有其他几种实现方法

        function Person() {this.age = 18}Person.prototype.foo = function () {console.log("this function")}function Student() {this.id = "101"}var obj = {}function F() { }F.prototype = Person.prototypeStudent.prototype = new F()var newObj = new Student()

定义一个新函数,使新函数的显式原型直接指向父类的显式原型
在构造这个新函数的对象时实际上是构造了一个指向父类的空的新对象
再将子类的显式原型指向这个新对象
这也是道格拉斯·克罗克福德提出来的方法

        function Person() {this.age = 18}Person.prototype.foo = function () {console.log("this function")}function Student() {this.id = "101"}var obj = Object.create(Person.prototype)Student.prototype = objvar newObj = new Student()

这里使用了Object.create方法,这个方法会创建一个空对象并将这个空对象的隐式原型指向你传入的对象
可能存在一些兼容性问题

寄生继承

最后我们将原型继承封装成一个函数

        function inherit(Subtype, Supertype) {function F() { }F.prototype = Supertype.prototypevar obj = new F()Subtype.prototype = objObject.defineProperty(Subtype.prototype, "constructor", {enumerable: false,value: Subtype})}

这个inherit就是寄生继承的实现方法
这种方法同样由道格拉斯·克罗克福德提出

组合寄生继承

此时寄生继承已经能解决原型继承借用构造函数继承中的绝大部分问题,剩下的一个最大的问题就是还需要继承父类中的属性
为了解决这个问题我们需要综合上面所有的方法来得到最终的解决方案

        function inherit(Subtype, Supertype) {function F() { }F.prototype = Supertype.prototypevar obj = new F()Subtype.prototype = objObject.defineProperty(Subtype.prototype, "constructor", {enumerable: false,value: Subtype})}function Person() {this.age = 18}Person.prototype.foo = function () {console.log("this function")}function Student() {Person.call(this)this.id = "101"}inherit(Student, Person)var newObj = new Student()console.log(newObj.id)console.log(newObj.age)newObj.foo()

控制台结果如下
结果
这也是目前在ES6以前使用最多的继承解决方案

原型继承关系

最后我们再来梳理一下在JavaScript中的原型继承关系
Object是所有类的父类
Object的显式原型的隐式原型指向null

1

因为Object也是一个函数,也同样拥有隐式原型,它的隐式原型指向Function的显式原型
Function隐式原型同样指向自己的显式原型
因为Function显式原型是通过new Object创建出来的,所以它的隐式原型指向Object的显式原型

2

我们创建的函数的显式原型指向函数自己的显式原型
我们的函数本质上是通过new Function创建出来的
所以函数的隐式原型则指向Function的显式原型

3

我们通过foo创建出来的对象隐式原型指向foo的显式原型
通过new Object创建出来的对象隐式原型指向Object的显式原型

4

以上就是在JavaScript中的原型继承关系图
最后附带一张更加形象的示例图

最后

http://www.yayakq.cn/news/406359/

相关文章:

  • 公众微信网站建设口碑好的定制网站建设提供商
  • 网站要和别人做api 链接温州百度网站快速优化
  • 企业网站开发的背景和意义浙江省特种作业人员证书查询
  • 网站开发类毕业设计去类似美团网站做软件开发
  • 网站建设买了服务器后怎么做农业网站建设模板
  • 二级网站怎样做排名网站建设开发有限公司
  • 2017建站之星怎么样网络营销推广公司哪家好
  • 怎样运营推广网站建设个人网站需要备案吗
  • 网站建设规划案例自己做平台需要多少钱
  • 境外做网站网站网络销售网站设置
  • 南通做网站友情链接多久有效果
  • 中国小说网站策划与建设网站建设方案的企业
  • 大网站成本wordpress读取速度慢
  • 凡科做的网站为什么打不开网站上的美工图片要怎么做
  • wordpress标签别名百度智能小程序怎么优化排名
  • 免费行情软件网站大全网页版设计师做兼职的网站有哪些
  • 网站的设计费用三亚网站优化
  • 学校做网站需要多少钱小说网站制作模板
  • 免费注册企业网站不锈钢公司网站源码 网站建设 产品3级分类asp源码
  • 湛江个人网站制作在哪里做无锡网站设计无锡网站建设
  • 网站建设在淘宝怎么分类鹰潭北京网站建设
  • 安阳做推广网站做网站时怎么让边框细一点
  • 小学生入门编程用什么软件网站怎么做利于优化
  • 自己做自媒体在哪个网站比较好专门做10s视频的网站
  • 太原好的网站制作排名网站安全检测腾讯
  • 住建部官方网站郑州最好的人流医院
  • 2015做外贸网站好做吗深圳建设厅网站
  • 手机怎么登录自己做的网站企业营销网络建设
  • 龙华附近网站建设公司和孕妇做网站
  • seo网络优化专员富阳网站seo价格