首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >有没有一种方法可以创建行为像C++ RValues的JavaScript对象?

有没有一种方法可以创建行为像C++ RValues的JavaScript对象?
EN

Stack Overflow用户
提问于 2014-06-04 18:48:48
回答 1查看 2.2K关注 0票数 20

我是一名C++程序员,最近刚接触到JavaScript世界;为了理解和心理健康,我现在正在尝试将C++的一些设计模式应用到JavaScript中。

下面的代码在C++和Javascript中是等同的:

C++

代码语言:javascript
复制
// Class definition
template <typename T> class foo
{
public:
    // Constructor
    foo(T value) { this->value = value; }
    // Public function
    T twice() { return this->value + this->value; }

private:
    // Private function
    void bar() { }
    // Private member
    T value;
};

JavaScript

代码语言:javascript
复制
// "Class" definition and constructor
function foo(value)
{
    // "Private" member
    this.value = value;

    // "Private" function
    this.bar = function() { };
}

// Public function
foo.prototype.twice = function() { return this.value + this.value; };

这两个类的用法也很相似:

C++ live demo

代码语言:javascript
复制
foo<int> f1(1);
foo<std::string> f2("1");

std::cout << f1.twice() << '\n'; // output: 2
std::cout << f2.twice() << '\n'; // output: 11

JavaScript live demo

代码语言:javascript
复制
var f1 = new foo(1);
var f2 = new foo('1');

print(f1.twice()); // output: 2
print(f2.twice()); // output: 11

但是有一件事不能用JavaScript类来完成,而可以用C++类来完成:使用临时RValue来完成任务:

C++

代码语言:javascript
复制
std::cout << foo<float>(3.14f).twice() << '\n'; // output: 6.28

JavaScript

代码语言:javascript
复制
print(foo(3.14).twice()); // Uncaught TypeError: undefined is not a function

我认为JavaScript版本的错误是因为foo是一个函数,它不返回任何内容(undefined),所以一开始我想用下面的代码更改构造函数:

JavaScript

代码语言:javascript
复制
// "Class" definition and constructor
function foo(value)
{
    // "Private" member
    this.value = value;

    // "Private" function
    this.bar = function() { };

    return this; // <----- new code!
}

但是这根本不起作用;return this;指令返回的对象不是foo类型(foo(3.14) instanceof foofalse)。

在Chrome35.0.1916.114中调试时,指令return this;中的this类型为foo,但在这种情况下,类型更改为window

代码语言:javascript
复制
var x = foo(3.14); // x is typeof window

一旦做了介绍,问题就来了:

  • 当在外部捕获时,为什么构造函数内的this类型为foowindow类型为window
    • 是因为new运算符不是type

  • 是否有一种方法可以创建行为类似C++ RValues的JavaScript对象?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-04 19:16:09

在JavaScript中,将new关键字与函数一起使用时,该函数的行为与在不使用new关键字的情况下进行调用时的行为不同。有了它,函数就像一个类一样工作,一个新的对象从它被实例化,就像在传统的OOP语言中一样。此外,this上下文被设置为自身,并且忽略函数的返回值。

相反,如果没有new关键字,this上下文将被设置为全局作用域,对于浏览器来说,全局作用域是window对象,返回值可以由任何调用它的对象捕获。

可以创建类似于C++示例的内容,这样您就不需要new关键字,但它仍然返回一个新对象。

Fiddle

代码语言:javascript
复制
function foo(value) {
    function foo(value) {
        this.value = value;

        this.bar = function () {};
        this.twice = function() { return this.value + this.value; }
    }

    return new foo(value);
}

console.log( foo(3.14).twice() ); // 6.28

解释:

外部函数foo的行为类似于普通函数,并且无需new关键字即可调用。内部有一个内部的foo,它就像一个用new关键字调用的类。外部foo实例化内部foo的一个新实例并返回它。因此,它可以像C++示例一样使用。没有必要在外部函数中声明类函数,它只取决于您是否想要将其封装在外部函数中。

可见性

问题中的两个示例并不完全等价,因为JavaScript示例使用所有公共属性和方法,而C++示例将barvalue设置为私有。

下面是一个更接近C++版本的版本:

Fiddle

代码语言:javascript
复制
function foo(value) {
    function foo(value) {
        var value = value;

        function bar(){}
        this.twice = function() { return value + value; }
    }

    return new foo(value);
}

console.log( foo(3.14).twice() ); // 6.28 
console.log( foo(3.14).value ); // undefined because it's private
console.log( foo(3.14).bar() ); // undefined because it's private

正如您从测试用例中看到的,valuebar是不可公开访问/可见的。这是通过不使用this前缀而使用var关键字(定义局部变量)声明value来实现的。该函数声明为声明,而不是表达式。在JavaScript中,没有像OOP语言那样声明/区分公共和私有属性或方法的正式方法。

您可能已经注意到,上面的示例没有使用prototype来声明任何方法。这样做的原因是,原型方法总是声明具有公共可见性的方法,并且原型方法不能从“类”或函数中看到任何变量。问题中的代码注释表明,在函数体中使用this.bar会使其成为私有的,但事实并非如此。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24035431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档