javascript高级程序设计 安全作用域构造函数 问题

发布于 2022-09-06 05:58:57 字数 914 浏览 29 评论 0

书上的解释不太理解,求大神帮解释下。
为什么第一种没有继承到sides属性

clipboard.png

// 创建作用域安全的构造函数
function Polygon(sides) {
    if (this instanceof Polygon) {
        console.log('this', this);
        this.sides = sides;
        this.getArea = function(){
            return 0;
        }
    } else {
        return new Polygon(sides);
    }
}

// 非作用域安全的构造函数
function Rectangle(width, height) {
    Polygon.call(this, 2);  
    this.width = width;
    this.height = height;
    this.getArea = function (){
        return this.width * this.height;
    }
}

let rect = new Rectangle(5,10);
console.log(rect.sides);

为什么rect没有继承到side属性

而通过原型就可以

Rectangle.prototype = new Polygon();
let rect = new Rectangle(2,4);
console.log(rect.sides);// 2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

作业与我同在 2022-09-13 05:58:57

第一种情况,当你let rect = new Rectangle(5,10);时,此时rect是Rectangle的一个实例,Polygon.call(this, 2); 中this指代rect,你把rect作为Polygon的this来调用Polygon,当在Polygon中判断(this instanceof Polygon)这句话时,发现this也就是rect不是Polygon的实例,根据instanceof的用法它会查找this的原型链,原型链中是否有Polygon的实例,如果找到就返回true。显然没找到,所以实际上Polygon.call(this, 2);这句话相当于执行了new Polygon(2),与rect无关,所以rect中没有sides属性。
第二中情况:Rectangle.prototype = new Polygon();你让Rectangle.prototype变为Polygon的一个实例(这其实是javascript的原型继承),看个例子:

function FOO(){} 
function Foo(){} 
Foo.prototype = new FOO();
 
var foo = new Foo();          //
foo.__proto__===Foo.prototype;
console.log(foo instanceof Foo)//true 
console.log(foo instanceof FOO)//true,根据foo的原型链找到了FOO的实例

因此第二种情况中Polygon.call(this, 2);它执行的是if语句中的代码,把sides和getArea放到了this中,所以rect.sides会是2。

家住魔仙堡 2022-09-13 05:58:57

Polygon.call(this, 2);的时候 Polygon 中的this指向 Rectangle 而不是 Polygon
而当你 new Polygon的时候,this指向就是 Polygon了

主要还是call的用法的关系

心房的律动 2022-09-13 05:58:57

写在注释里了

    // 创建作用域安全的构造函数
    function Polygon(sides) {
        if (this instanceof Polygon) {
            debugger;  // (3) 此时 this 是 Polygon 实例,所以执行到了这里
            console.log('this', this);  
            this.sides = sides;
            this.getArea = function(){
                return 0;
            }
        } else {
            debugger;  // (1) 调用 Polygon.call(this, 2) 时 this 不是 Polygon 的实例 所以先执行到了这里
            return new Polygon(sides);  // (2) 此时返回了一个 Polygon实例
        }
    }

    // 非作用域安全的构造函数
    function Rectangle(width, height) {
        // 执行(2)返回了一个Polygon实例 但是你没有用到 也就是没有赋给变量 所以在 new Rectangle(5,10) 时候不会继承sides
        Polygon.call(this, 2); 
        this.width = width;
        this.height = height;
        this.getArea = function (){
            return this.width * this.height;
        }
    }

    let rect = new Rectangle(5,10);
    console.log(rect);

    // Rectangle 的原型链直接指向了一个 Polygon 实例, 那么new Rectangle(5,10)时候, 所有的Rectangle实例都会继承sides,因为查找对象属性时如果在当前对象上找不到,就会顺着原型链一直找
    Rectangle.prototype = new Polygon(); 

    // 比如这个例子
    let obj = { a:1 };
    obj.__proto__.b = 2; // 属性b在obj的原型链上
    console.log(obj);  // { a: 1 }
    console.log(obj.b); // 2
用心笑 2022-09-13 05:58:57

if (this instanceof Polygon)
这句不是判断了么?

如果当前的this是由Plolygon构造的就把当前this.sides = sides,否则返回实例化过的Plolygon。

楼主的问题真是漏洞百出啊。首先js继承没搞清楚,其次instanceof不懂,再次,call具体作用没搞清楚····

他是夢罘是命 2022-09-13 05:58:57

JavaScript 的继承是通过原型链实现。
没有下面的语句:

Rectangle.prototype = new Ploygon();

无法实现 Rectangle 继承 Polygon。

在 Rectangle 函数中,Polygon.call(this,2) 只是相当于调用了基类的构造函数。但是前提是,你要先实现继承,没有继承关系,这个调用没啥效果。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文