javascript - js动态原型模式使用对象字面量报错
高洛峰
高洛峰 2017-04-11 13:08:16
[JavaScript讨论组]
// 动态原型模式「

function Person(name,age){
    this.name=name;
    this.age=age;
    if(typeof this.load!='function'){
        Person.prototype={
            constructor:Person,
            job:'vip',
            load:function(){
                console.log(name,age);
            }
        }
    }
}

var toti=new Person('toti',18);
toti.load();
// 」动态原型模式

网上查的答案都无法让我很满意,没有答到点子上,希望有大神解惑。
我希望了解到使用对象字面量报错的原理,是因为什么,求详细解答!

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

全部回复(5)
大家讲道理

假设有一个构造函数:

function CO(){
    this.p = “I’m in constructed object”;
    this.alertP = function(){
        alert(this.p);
    }
}
var o2 = newCO();

那么,在使用new操作符来调用一个构造函数的时候,发生了什么呢?其实很简单,就发生了四件事:

var obj  ={};
obj.__proto__ = CO.prototype;
CO.call(obj);
return obj;

所以再看你的例子,可以看出_proto_的设置是先于你的设置动态原型(prototype)的语句执行的,并且重新设置的原型不会影响到已经创建的对象。

ps:参考自网上。

大家讲道理

解决方法不是没有:

function Person (name, age) {
    this.name = name
    this.age = age
    if (typeof this.load !== 'function') {
        Person.prototype.load = function () {
            console.log('name is %s, age is %s', this.name, this.age)
        }
        Person.prototype.job = 'vip'
    }
}

但是为什么要这样做呢?

高洛峰

以上回答都没有说到重要。

何为 new

创建一个实例的时候会两个过程:

1、构造 Person 的时候,会把 toti 以传参的形式传递给构造函数,并替换 this
2、设置原型链。

因此,创建一个实例以后,其实原型链已经确认了,而后你再调用 load 肯定就找不到鸟。

function Person(name,age){
    this.name=name;
    this.age=age;
}
Person.prototype={
    constructor:Person,
    job:'vip',
    load:function(){
        console.log(this.name, this.age);
    }
}

var toti=new Person('toti',18);
toti.load();

以上。

迷茫

字面量创建的对象其原型对象被重写了

var proto="";
function Person(name,age){
    this.name=name;
    this.age=age;
    if(typeof this.load!='function'){
          proto = Person.prototype;//未经过字面量重写的原型对象
        Person.prototype={
            constructor:Person,
            job:'vip',
            load:function(){
                console.log(name,age);
            }
        }
        console.log(proto == Person.prototype) //false 说明Person原型对象已被重写改变

    }
}

var toti=new Person('toti',18);
toti.load();
PHP中文网

new一个对象时,构造函数会先做两件事,一是设置this值为new出来的空对象,而是设置好这个空对象的原型,调用构造函数只是给这个空对象添加属性。
第一次new对象时,这个对象的原型链已经确定了。Person.prototype = {}的形式只改变了Person的prototype属性,没有改变这个对象的原型,所以第一个对象找不到load、job等属性。Person.prototype.prop = value的形式既改变了Person的prototype又给对象的原型对象(__proto__)增加了属性prop.

function Person(name,age){
    this.name=name;
    this.age=age;
    if(typeof this.load!='function'){
        Person.prototype={
            constructor:Person,
            job:'vip',
            load:function(){
                console.log(name,age);
            }
        }
    }
}
console.log((new Person()).load);//undefined 先new一个会设置好Person的prototype属性,也就是Person类对象的原型(__proto__)
var toti=new Person('toti',18);
toti.load();//这里就没问题了。
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号