Javascript 理解typescript生成的_扩展函数?
我正在玩并试图理解编译器生成的已编译Javascript代码 打字脚本代码:Javascript 理解typescript生成的_扩展函数?,javascript,prototype,javascript-objects,proto,javascript-inheritance,Javascript,Prototype,Javascript Objects,Proto,Javascript Inheritance,我正在玩并试图理解编译器生成的已编译Javascript代码 打字脚本代码: class A { } class B extends A { } var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && funct
class A { }
class B extends A { }
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var A = /** @class */ (function () {
function A() {
}
return A;
}());
var B = /** @class */ (function (_super) {
__extends(B, _super);
function B() {
return _super !== null && _super.apply(this, arguments) || this;
}
return B;
}(A));
生成的Javascript代码:
class A { }
class B extends A { }
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var A = /** @class */ (function () {
function A() {
}
return A;
}());
var B = /** @class */ (function (_super) {
__extends(B, _super);
function B() {
return _super !== null && _super.apply(this, arguments) || this;
}
return B;
}(A));
根据的Javascript继承如下所示:
在Typescript生成的代码中,我不理解的部分如下
一,。这条路线的目的是什么?看起来它正在将A的所有键复制到B中?这是对静态属性的一种攻击吗
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
二,。这是干什么的
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
我不明白这一部分:(\uuuuu.prototype=b.prototype,new())
为什么函数B()返回这个值
return _super !== null && _super.apply(this, arguments) || this;
如果有人能逐行向我解释这一点,我将不胜感激。我自己也对这一点很好奇,但找不到快速的答案,所以这里是我的分类: 它的作用 __extends是一个函数,它模拟面向对象语言中的单类继承,并为派生函数返回一个新的构造函数,该派生函数可以创建从基对象继承的对象 注1:
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __extends = (this && this.__extends) || (function () {
// gobbledygook
})();
我自己并没有意识到这一点,但是如果你做了如下的事情,其中所有的值都是真的,那么变量就被设置为最后一个测试项目的值,除非其中一个是假的,在这种情况下,变量被设置为假的:
// value1 is a function with the definition function() {}
var value1 = true && true && function() {};
// value2 is false
var value2 = true && false && function() {};
// value3 is true
var value3 = true && function() {} && true;
我之所以提到这一点,是因为当我看到这个javascript时,这是最让我困惑的事情,它在扩展函数定义中被使用了好几次
注2:
参数d(可能代表派生)和b(可能代表基)都是构造函数,而不是实例对象
注3:
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __extends = (this && this.__extends) || (function () {
// gobbledygook
})();
prototype
是函数的属性,是“构造函数”函数使用的原型对象(即使用new()
创建的对象)
使用new
操作符构造新对象时,新对象的内部[[PROTOTYPE]]
aka\uuuu proto\uuu
设置为函数的PROTOTYPE属性
function Person() {
}
// Construct new object
var p = new Person();
// true
console.log(p.__proto__ === Person.prototype);
// true
console.log(Person.prototype.__proto__ === Object.prototype);
这不是副本。这就是目标
当您创建文字对象时,如
var o = {};
// true
console.log(o.__proto__ === Object.prototype);
新对象的\uuu proto\uu
设置为对象.prototype
(内置对象构造函数)
您可以使用object.create
将对象的原型设置为另一个对象
当在当前对象上找不到属性或方法时,将检查对象的[[PROTOTYPE]]
。如果找不到,则检查该对象的原型。所以它会检查原型,直到它到达最终的原型对象,object.prototype
。记住,没有东西是复制品
注4
在Javascript中模拟继承时,将设置“构造函数”函数的原型
function Girl() {
}
Girl.prototype = Object.create(Person.prototype);
// true
console.log(Girl.prototype.__proto__ === Person.prototype);
// true
console.log(Girl.constructor === Function);
// Best practices say reset the constructor to be itself
Girl.constructor = Girl;
// points to Girl function
console.log(Girl.constructor);
注意我们如何将构造函数指向Girl,因为it Person的构造函数指向内置的函数
您可以在以下位置查看上面的代码:
原件:
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __extends = (this && this.__extends) || (function () {
// gobbledygook
})();
故障:
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __extends = (this && this.__extends) || (function () {
// gobbledygook
})();
记住上面的注释1,第一部分(和结尾)创建了一个名为u_extends的变量,其目的是保存一个函数来设置派生类的原型
(this && this.__extends)
正在做我的注释1解释的事情。如果这是真的,而这是真的,那么变量uu extends已经存在,因此设置为自身的现有实例。如果不是,则设置为| |之后的内容,这是一个iife(立即调用的函数表达式)
现在对于gobbledygook,它是uu的实际定义扩展:
名为extendStatics的变量设置为脚本运行环境的内置Object.setPrototypeOf函数()
或
它创建自己的版本
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
在注释3中,我讨论了\uuu proto\uuu
aka[[PROTOTYPE]]]
以及如何设置它。代码
{ __proto__: [] } instanceof Array
是一种测试,通过将文字对象的\uuuuu proto\uuu
集与文字数组与数组内置函数进行比较,确定当前环境是否允许设置此属性
(__.prototype = b.prototype, new __()
回到我上面的注释1,请记住javascript instanceof操作符返回true或false(),如果环境对一个对象进行求值,并将其prototype属性设置为内置数组,那么ExtendStatics将设置为
function (d, b) { d.__proto__ = b; })
如果环境没有以这种方式进行评估,则extendStatics设置为:
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }
之所以这样做,是因为在ECMAScript 2015(以及根据)之前,\uuuuuuu proto\uuuuuu
从来都不是官方ECMAScript标准的一部分,只是为了向后兼容)。如果受支持,则使用\uuuu proto\uuu
函数,或者使用“滚动您自己的”版本,该版本将用户定义的属性从对象b复制到对象d
现在已经定义了extendStatics函数变量,将返回一个调用extendStatics内部任何内容(以及其他内容)的函数。请注意,参数“d”是子类(继承的)而“b”是超类(继承的):
调用extendStatics将其分解,第一个参数对象(d)的原型设置为(b)(回想上文注释3):
在下一行中,将声明一个名为“_u”的构造函数,该构造函数将其构造函数指定为派生(d)构造函数:
function __() { this.constructor = d; }
如果基本(b)构造函数
函数恰好为空,这将确保派生的构造函数将保留其自己的原型
从,Object.prototype.constructor(所有对象都是javascript中的对象):
返回对创建的对象构造函数的引用
实例对象。请注意,此属性的值是
引用函数本身,而不是字符串
// refactored version of __extends for better readability
if(!(this && this.__extends)) // skip if already exists
{
var __extends = function(derived_cl, base_cl) // main function
{
// find browser compatible substitute for implementing 'setPrototypeOf'
if(Object.setPrototypeOf) // first try
Object.setPrototypeOf(derived_cl, base_cl);
else if ({ __proto__: [] } instanceof Array) // second try
derived_cl.__proto__ = base_cl;
else // third try
for (var p in base_cl)
if (base_cl.hasOwnProperty(p)) derived_cl[p] = derived_cl[p];
// construct the derived class
if(base_cl === null)
Object.create(base_cl) // create empty base class if null
else
{
var deriver = function(){} // prepare derived object
deriver.constructor = derived_cl; // get constructor from derived class
deriver.prototype = base_cl.prototype; // get prototype from base class
derived_cl.prototype = new deriver(); // construct the derived class
}
}
}
// Barebone version of __extends for best comprehension
var __extends = function(derived_cl,base_cl)
{
Object.setPrototypeOf(derived_cl,base_cl);
var deriver = function(){} // prepare derived object
deriver.constructor = derived_cl; // get constructor from derived class
deriver.prototype = base_cl.prototype; // get prototype from base class
derived_cl.prototype = new deriver(); // construct derived class
}