V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
cheroky
V2EX  ›  JavaScript

看了《JavaScript 高级程序设计》,有个关于动态原型模式的问题

  •  
  •   cheroky · 2016-07-11 10:07:37 +08:00 · 3227 次点击
    这是一个创建于 2838 天前的主题,其中的信息可能已经有所发展或是发生改变。

    书上介绍了动态原型模式的代码如下:

    function Person(name,age,job) {
        //property
        this.name = name;
        this.age = age;
        this.job = job;
        //method
        if(typeof this.sayName != "function") {
            Person.prototype.sayName = function() {
                console.log(this.name);
            }
            
            //Person.prototype = {
            //    sayName: function() {
            //        console.log(this.name);
            //    }
            //} //这样的写函数的方式报错说没有 sayName 这个函数
        }
    }
    
    当我用注释的 sayName 写法时会提示找不到 sayName 这个函数,为什么??
    两种方式有什么异同吗?我记得书上提过第二种只是对第一种声明变量多的简便写法。
    
    10 条回复    2016-07-12 14:13:52 +08:00
    judasnow
        1
    judasnow  
       2016-07-11 10:13:33 +08:00
    你直接把 prototype 给覆盖了。放到构造函数外面就行了。
    Parabolazz
        2
    Parabolazz  
       2016-07-11 10:27:18 +08:00
    你看高程 156 页,用对象字面量的方法相当于重写了整个原型。切断了构造函数和最初的原型之间的联系。
    我的理解是你这时 new 一个新实例,实例的原型并没有 sayName 方法,因为 sayName 方法保存在新的原型对象上了。
    shyling
        3
    shyling  
       2016-07-11 10:31:17 +08:00 via iPad
    把注释的部分放到 Person 外面
    coolzjy
        4
    coolzjy  
       2016-07-11 10:33:29 +08:00
    judasnow
        5
    judasnow  
       2016-07-11 11:05:08 +08:00
    @judasnow 研究了下,忽略我的第一句话吧 233
    songz
        6
    songz  
       2016-07-11 11:25:13 +08:00
    Person.prototype.sayName
    learnshare
        7
    learnshare  
       2016-07-11 11:32:57 +08:00
    不要覆盖 prototype ,用 #6 的方式,扩展 prototype 。
    palmers
        8
    palmers  
       2016-07-11 15:07:41 +08:00
    据我的分析是这样的: 你注释的内容改变了对象的原型对象, 所以,通过 Person `new`操作符实例化的对象的原型是 Object 不再是 Person.prototype 了,然而, sayName 函数并不在 Person 对象的原型上,所以找不到,注释代码中 sayName 函数实际上是在通过 new Person()得到的对象的构造函数的原型上,也就是 Person.prototype.constructor.__proto__ ;
    Cytrs
        9
    Cytrs  
       2016-07-12 08:18:05 +08:00   ❤️ 1
    之前刚好看到了一篇文章 https://segmentfault.com/a/1190000000602050
    Sparetire
        10
    Sparetire  
       2016-07-12 14:13:52 +08:00
    准确说应该是创建的第一个对象没有 sayName 方法,之后创建的对象都有 sayName 方法,可以试试
    因为创建第一个对象的时候的原型对象没有 sayName 方法,之后每次创建对象都重写了原型,且这些原型都有 sayName 方法,所以只有第一个对象没有 sayName ,之后的都有
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4081 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 05:11 · PVG 13:11 · LAX 22:11 · JFK 01:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.