构造函数和原型

构造函数和原型,第1张

在ES6之前,对象不是通过类创建的,而是用构造函数的特殊函数来定义。

创建对象可以通过以下三种方式:

构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new 一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到一个函数里面。

普通函数

如果没有设置return,调用时则返回undefined

构造函数

不需要设置return,实例时默认返回该对象

构造函数通过原型定义的函数是所有实例对象共享的

JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象,这个对象的所有方法和属性,都会被构造函数所拥有。

我们可以把相同的方法,直接定义在prototype对象上,这样所有实例对象就可以共享这些方法。

一般情况下,公橘雹拿共属性定义到构造函肆森数里面,而公共方法定义在原型对象上。

原型的主要作用是共享方法

创建对象时系统会自动添圆搭加一个 proto 属性指向我们构造函数的原型对象 prototype

对象原型(__proto __)和 构造函数原型对象(prototype)里面都有一个cunstructor属性,称为构造函数,因此它指向构造函数本身。

当Star.prototype 以对象的形式添加方法时,会删除constructor属性,所以需要我们手动添加回来

我在Object原型对象中定义个dacen方法,ldh实例对象也能访问到。Object是原型链的尽头

查找机制:

ldh实例首先会在自身对象中查找,如果找不到该方法,则会在Stat原型对象中找,如果还找不到,就会通过__ proto__原型,到Object原型对象上找,直到为null。

函数对象都是有Function函数生成的,而Function自身也是函数,则有Function.__ proto__ === Function.prototype // true (函数是自身的实例)

Object 也是构造函数,所以Object.__ proto__ === Function.prototype //对象是函数的实例

1、 Foo.getName()

为什么输出2,不是3?这就得说说构造函数的静态属性与实例属性。 我们都知道函数属于对象,而对象拥有可以自由添加属性的特性,函数也不例外,构造函数也是函数:

比如这个例子中,我为构造函数Fn添加了静态属性person与静态方法sayName,我们可以通过构造函数Fn直接访问。在JS中,我们将绑定在构造函数自高衡身上的属性方法称为静态成员,静态成员可通过构造函数自身访问,而实例无法访问。

那有什么属性是实例可以访问而构造函数自身无法访问的呢,当然有,比如实例属性。这里我将实例属性细分为构造器属性与原型属性两种,看下面的例子:

2、 getName()

这里考的是变量提升与函数声明提升 ,function getName()变量提升,声明后被 getName= function(){...}覆盖,输出4

3、 Foo().getName()

getName是全局变量,所以在函数Foo内也能直接访问,于是getName被修改成了输出1的函数,之后返回了一个this。

由于Foo().getName()等同于window.Foo().getName(),所以this指向window,这里返回的this其实就是window。

4、 getName()

这里输出1已经毫无悬念,上一分析中,getName的值在Foo执行时被修改了,所以再调用getName一样等同于window.getName(),同样是输出1。

5、 new Foo.getName()

等价于new (Foo.getName()),在分析一中我们已经知道了Foo.getName是Foo的静态方法,这里的getName虽然是Foo的静态方法,但是既没有继承Foo的原型,自身内部也没提供任何构造器属性(this.name这样的),所以new这戚知做个静态方法只能得到一个空属性的实例。

因此这里new的过程就相当于单纯把Foo.getName执行了一遍输出2,然后返回了一个空的实例

6、 new Foo().getName()

这里考了new基本概念,首先这个调用分为两步,第一步new Foo()得到一个实例,第二步调用实例的getName方法

7、 new new Foo().getName()

第一眼也是看的我很懵,我们知道new一个函数都是new fn(),函数带括号的。所以这里其实可以拆分成这样:

由于构造函数Foo自身啥构造器属性都没有,只有原型上有一个输出3的原型方法,所以实例a是一猛虚个原型上有输出3的函数getName。

那么第二步,由于原型上的getName方法也没提供构造器属性,自身原型上也没属性,所以第二步也算是单纯执行a.getName()输出3,然后得到了一个什么自定义属性都没有实例。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/bake/11982425.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存