web-dev-qa-db-ja.com

これを返すことを避けるために、コンストラクタはどの値を返すことができますか?

thisキーワードを使用してコンストラクターが呼び出されたときに、Javascriptのreturnステートメントがnew以外の値を返す正確な状況は何ですか?

例:

function Foo () {
  return something;
}

var foo = new Foo ();

間違っていない場合、somethingが非関数プリミティブの場合、thisが返されます。それ以外の場合は、somethingが返されます。これは正しいです?

IOW、どの値がsomething(new Foo () instanceof Foo) === false

87
Thomas Eding

正確な条件は、 new 演算子で使用される_[[Construct]]_内部プロパティで説明されています。

ECMA-262 3日から。エディションの仕様:

13.2.2 _[[Construct]]_

FunctionオブジェクトFの_[[Construct]]_プロパティが呼び出されると、次の手順が実行されます。

  1. 新しいネイティブECMAScriptオブジェクトを作成します。
  2. Result(1)_[[Class]]_ プロパティを_"Object"_に設定します。
  3. Fのプロトタイププロパティの値を取得します。
  4. Result(3)がオブジェクトの場合、Result(1)_[[Prototype]]_ プロパティをResult(3)に設定します。
  5. Result(3)がオブジェクトでない場合、Result(1)_[[Prototype]]_ プロパティを元のObjectに設定します 15.2.3.1 で説明されているプロトタイプオブジェクト。
  6. F_[[Call]]_ プロパティを呼び出し、this値としてResult(1)を提供し、引数リストを提供します引数値として_[[Construct]]_に渡されます。
  7. Type(Result(6))Objectの場合、Result(6)を返します。
  8. Result(1)を返します。

手順7と8を見ると、Result(6)Fコンストラクター関数から返される値)の型がの場合にのみ新しいオブジェクトが返されます。 notオブジェクト。

156
CMS

具体例 http://jsbin.com/zivivucahi/1/edit?html,js,console,output

/*
ECMA 262 v 5
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
"4.3.2
primitive value
member of one of the types Undefined, Null, Boolean, Number, Symbol, or String as defined in clause 6"
*/

var Person = function(x){
  return x;

};


console.log(Person.constructor);
console.log(Person.prototype.constructor);
console.log(typeof(Person));
console.log(typeof(Person.prototype));

function log(x){
  console.log(x instanceof Person);
  console.log(typeof x);
  console.log(typeof x.prototype);
}

log(new Person(undefined));
log(new Person(null));
log(new Person(true));
log(new Person(2));
log(new Person(""));

//returns a function not an object
log(new Person(function(){}));


//implementation?
//log(new Person(Symbol('%')));
4
philn5d

この問題に関するドキュメントは見つかりませんでしたが、あなたは正しいと思います。たとえば、コンストラクタからnew Number(5)を返すことはできますが、リテラル5を返すことはできません(無視され、代わりにthisが返されます)。

2
mkrause

簡単な言葉でいくつかのポイントをしようとしています。

JavaScriptでは、関数でnewキーワードを使用し、次の場合、

  1. 関数は何も返さず、目的のオブジェクトを返します
function User() {
  this.name = 'Virat'
}

var user = new User();
console.log(user.name); //=> 'Virat'
  1. 関数は任意のtruthy複合オブジェクト[オブジェクト、配列、関数など]を返します。その複合オブジェクトが優先され、user変数は返された複合オブジェクトを保持します
function User() {
  this.name = 'Virat';
  return function(){};
}

var user = new User();
console.log(user.name); //=> undefined
console.log(user); //=> function
  1. 関数はリテラルを返し、コンストラクターが優先され、目的のオブジェクトを返します
function User() {
  this.name = 'Virat';
  return 10;
}

var user = new User();
console.log(user.name); //=> 'Virat'
1
Ravindra Thorat

補足として、戻り値またはthisは方程式の一部にすぎません。

たとえば、これを考慮してください:

_function Two() { return new Number(2); }
var two = new Two;
two + 2; // 4
two.valueOf = function() { return 3; }
two + 2; // 5
two.valueOf = function() { return '2'; }
two + 2; // '22'
_

ご覧のとおり、.valueOf()は内部的に使用され、楽しみと利益のために悪用される可能性があります。次のような副作用を作成することもできます。

_function AutoIncrementingNumber(start) {
    var n = new Number, val = start || 0;
    n.valueOf = function() { return val++; };
    return n;
}
var auto = new AutoIncrementingNumber(42);
auto + 1; // 43
auto + 1; // 44
auto + 1; // 45
_

これにはsomeのような実用的なアプリケーションが必要だと想像できます。また、明示的にNumberである必要はありません。オブジェクトに_.valueOf_を追加すると、数値として動作できます。

_({valueOf: function() { return Math.random(); }}) + 1; // 1.6451723610516638
_

これを利用して、たとえば、常に新しいGUIDを返すオブジェクトを作成できます。

0
Camilo Martin