js中构造原型,原型链

构造函数 和原型

以前的创建对象的三种方式:

1.对象字面量

2.new object()

3.自定义构造函数

new 在执行时会做的四件事:

1.在内存中创建一个空的内存对象

2.让this指向这个对象

3.执行构造函数中的代码,给这个新对象添加属性和方法

4.返回这个新对象(不需要return)

function star(uname,age){

this.uname=uname;

this.age=age;

this.sing=function(){

}

}

var ldh=new star();

star.sex='男'; 这个就是静态成员

静态成员和实例成员:

实例成员:

就是构造函数内部通过this添加的成员

实例成员只能通过实例化的对象来访问。

ldh.uname;

静态成员:

在构造函数本身上添加的成员

静态成员只能通过构造函数来访问

star.sex;

构造函数存在浪费内存的问题:因为构造函数中的方法属于复杂数据类型,每一个方法都需要开辟一个新的内存空间。

构造函数原型 prototype

构造函数通过原型分配的函数是所有对象所共享的,每一个构造函数都又一个原型对象。

我们可以把那些不变的方法,直接定义在prototype 对象上,这样所有对象的实例就可以共享这些方法。所以写法变为:

function star(uname,age){

this.uname=uname;

this.age=age;

}

star.prototype.sing=function(){}

一般情况下,我们公共属性定义到构造函数里面,公共的方法我们都放到原型对象身上。

对象身上系统自己添加一个_proto_属性,指向我们构造函数的原型对象。

代码方法的找寻:首先先看实例化对象上是否有这个方法,如果有就执行,如果没有因为_proto_的存在就去构造函数原型对象prototype身上去查找方法。

constructor构造函数:

对象原型(__proto__)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性,constructor我们称为构造函数,因为它指回构造函数本身。

constructor主要用于记录该对象引用哪个构造函数,它可以让原型对象重新指向原来的构造函数。

小问题:当我们给原型对象赋值时:

star.protopyte={

sing:function(){},

movic:function(){}

}

当我们这样操作时,和上面的star.prototype.sing=function(){}大不相同

第二个操作是给star的原型对象添加属性,所以原型对象中默认的constructor不会被覆盖。第一个操作是重新创建了一个对象然后将star的原型对象全部给覆盖掉了,所以constructor属性也没有了,当然它就不能指回原来的构造函数。所以我们就需要进行手动指回:

star.protopyte={

constructor:star, //手动指回star构造函数

sing:function(){},

movic:function(){}

}

 

总结:每一个构造函数中都存在一个原型对象prototype,构造函数可以通过prototype指向它的原型对象,然后在原型对象中有一个constructor属性可以指回构造函数,构造函数实例化出的对象中

包含了一个原型对象__proto__它里面也有一个constructor属性指向prototype。

成员的查找机制:

先在自身上(ldh)找有没有这个成员,有就返回 ,没有就去prototype上找。如果还没有就去Object上去找。

原型对象中this指向

1.在构造函数中,里面的this指向的是对象实例

2.原型对象函数中(prototype)里面的this 指向的是 对象实例

this只有被调用的时候才知道指向的是谁

可以通过原型对象扩展内置对象:

//原型对象的应用,扩展内置对象方法

        Array.prototype.sum = function() {

            var sum = 0;

            for (var i = 0; i < this.length; i++) {

                sum += this[i];

            }

            return sum;

        }

        var arr = [1, 2, 3];

        console.log(arr.sum());

继承:

call() 调用这个函数,并且修改函数运行时的this指向

fun.call(thisArg,arg1,arg2) thisArg:当前调用函数this的指向对象,arg1,arg2:传递的其他参数

function fu(){}

var o={}

fu.call(o)这样fu这个函数this指向的对象就改为了o这个对象

利用父构造函数继承属性:

function Father(uname ,age){

this.uname=uname;

this.age=age;

}

function Son(uname ,age){

Father.call(this,uname,age) //这个this指向的是son的实例对象

}

var son =new Son('ldh',18);这样子构造函数就可以继承父构造函数的属性

如果属性或者方法在原型对象上,Son就不会得到。Father.call(this,uname,age)这个得到的只是父亲的构造函数

利用原型对象继承方法:

 

Son.prototype=Father.prototype 不行,因为相当于把地址值赋值给了Son.prototype 如果儿子的原型对象发生改变那么父亲的原型对象也会发生改变

Son.prototype =new Father();

通过实例对象的__proto__可以得到Father原型对象中的方法,这时候Son.prototype 被Father实例覆盖了 所以constructor指向的是Father构造函数。

Son.prototype.constructor=Son; 让Son原型对象指回Son的构造函数

类的本质:

类的本质其实还是一个函数,也可以理解为构造函数的另一种写法。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值