浅谈prototype、__proto__和继承

在谈及prototype、__proto__和继承之前,先说说js对象

1. js对象

    1.1 new(当然不仅仅new可以创建一个对象,var obj = {a = "a", b = "b"};也是一个对象)

        js的new类似于Java,new操作相当于3个操作:
(1)在系统堆中申请一个实例空间,实例空间存放该类的所有非静态成员,若无非静态成员,则申请一段空间,像java的ArrayList一样有初始空间;
(2)在系统堆栈中申请一个指针字节空间,将步骤一申请的实例空间首地址存入该指针字节空间,该指针又被称为this;

(3)对被实例化对象的非静态成员通过this赋初值,相当于将自身类当做函数使用;

    1.2 对象的本质是键值对集合

        相关js代码如下:

            var arr = [];        //相当于创建了一个数组类型的对象arr

    console.log("arr.length", arr.length);
    arr["1"] = 1;     //该对象为数组类的对象,故被解释为arr[1],下标0,1两个元素,故length=2;
    console.log("arr.length", arr.length);
    arr["a"] = 2;     //相当于arr.a,给arr对象增加了一个成员a
    console.log("arr.a", arr.a);

    console.log("arr.length", arr.length);

            输出如下

           

            表明插入a时长度未变化

            var obj = new Object;

    obj.2 = 2;  //语法错误,表明对象.成员,"obj.2"相当于给对象put一个键,键需满足变量名命名原则,键需为String类型,故语法错误,从而推断出对象相当于键值对集合


2. js对“对象.成员”的解释

    对于"对象.成员"的解释,浏览器有两种完全不同的方式:左值方式和表达式方式。
 2.1、左值方式:首先检查相关成员是否在本对象的键值对集合中存在,
  若存在,则更改,结束!
若不存在,则创建该键值对,结束!
 2.2、表达式方式:首先检查相关成员是否在本对象的键值对集合中存在,
  若存在,则输出,结束!
  若不存在,则沿着__proto__(原型链),在原型的键值对集合中查找,直到找到根集合(Object的prototype),

  若依然找不到,则输出undefined,结束;                                                                                                                         若有任何一次找到,则输出,结束!

进入正题:

3. prototype(原型)&__proto__(原型链)

   3.1. prototype指向自身(包括构造方法和静态成员),仅类存在prototype,代码如下:

        klass = function() {
this.member1 = "member1";
console.log("成功输出");
}
klass.prototype.member = "hello";
        console.log(klass.prototype);

console.log(window);

        

        var klass = function() {

this.member1 = "member1";
this["member2"] = "member2";
console.log("成功输出");
}

klass.prototype.constructor();

        

表明prototype必含constructor()函数,该函数指向自身函数;

        该函数指向自身函数是什么意思呢?,3.2予以解答

    3.2类类型含有原型prototype和原型链__proto__,对象仅含有__proto__, __proto__为“隐含”属性,__proto__可以更改对象所属类型,但以下划线开头的函数及对象是系统内部函数,不应在应用开发时使用

        一个类的原型链所对应的原型是判断instanceof的唯一标识,即a instanceof b; 若a的原型链指向的原型为b的原型,则返回true

        类的原型就是prototype所指向的内容;而对象的__proto__所指向的空间,就是其所属类型的prototype所指向的空间!

         js中的任何类有以下3层含义:

            (1)函数(可被直接调用)

            (2)对象(键值对集合)

            (3)类(原型所指对象必然存在constructor(),该构造函数指向该函数本身)。

        即,constructor()指向的是该类作为函数的应用;该类prototype是作为该类的对象,该类对象的__proto__也是该类的对象。

    图解:


    代码如下:

        var klass = function() {}

        var obj1 = new klass;
var object1 = new Object;
obj1.__proto__ = object1.__proto__;

console.log("obj1.__proto__ instanceof klass", obj1.__proto__ instanceof klass);

        console.log("klass.prototype instanceof Function:", klass.prototype instanceof Function);

        console.log("klass.prototype instanceof Object:", klass.prototype instanceof Object);

        输出如下:

    

    

    3.3. 修改prototype成员(“静态成员”)的值见代码

     var klass = function() {
}
klass.prototype.member1 = "member1";

var obj1 = new klass;

        obj1.member1 = 100;

console.log("obj1.member1:", obj1.member1);

        运行结果如下:

    

         出人意料的是,上面输出的并不是100,而是member1;这不能说明:member1不是“静态成员”!

 实际上,obj1.member1 = 100;的操作过程是:
 1、检查obj1是否存在"member1"关键字;
 2、上述检查发现,obj1本身的键值对集合中,不存在关键字"member1";
 3、于是,创建键值对:member1 -> 100!
 但是,ob1的原型链(__proto__)所指键值对集合中也存在member1!这个member1才是真正的“静态成员”!
 也就是说,如果想更改“静态成员”的值,不应该直接通过对象进行!而应该通过“类”进行!这也符合Java原则!
 在js中,如是引用和更改“静态成员”的值:

 klass.prototype.member1 = 100;

        运行结果如下:


4.经过上面的理解:所谓继承,就是将子类的prototype的__proto__由指向Object的prototype更改为指向其父类的prototype,但上面说__proto__属性不建议用户使用,所以,更改子类的prototype为父类的prototype。

相关继承代码如下:

function Extends (baseClass, currentClass) {
var Tmp = function () {};
Tmp.prototype = baseClass.prototype;

currentClass.prototype = new Tmp;
currentClass.prototype.constructor = currentClass;          //切记不要忘记恢复构造函数
};

var Animal = function (name) {
this.name = name;
};

function Dog (name, wang) {
Animal.call(this, name);
this.wang = wang;
};
Extends(Animal, Dog);

var dog = new Dog("犬类", "土狗");
console.log(dog);
console.log("dog instanceof Dog:", dog instanceof Dog);

console.log("dog instanceof Animal:", dog instanceof Animal);

输出如下:

        

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值