场景
你会收到一个的构造函数ctor,以及一个数组args,对于每个ctor,args长度不定。如何能够通用的构造一个实例呢?
简单而不用思考的方法:
var buildInstance = function(ctor, args) {
if (args.length == 0) {
return new ctor();
}
if (args.length == 1) {
return new ctor(args[0]);
}
if (args.length == 2) {
return new ctor(args[0], args[1]);
}
if (args.length == 3) {
return new ctor(args[0], args[1], args[2]);
}
};
It works.
自己实现“new”
但是聪明而又懒惰的程序员显然不会满足用这种方式写出的代码,它太不时髦了。
我们考虑一下new ctor的时候,程序做了什么?
1、构造了一个新的object对象o
2、使o的原型指向ctor的prototype
3、对o调用了ctor
了解了以上原理之后,我们也可以自己来实现“new”,代码如下:
var projection = function(o) {
var F = function() {};
F.prototype = o;
return new F();
};
var buildInstance = function(ctor, args) {
var proto = projection(ctor.prototype);
ctor.apply(proto, args);
return proto;
};
我们来测试一下
var MockClass = function() {
this.args = arguments;
};
MockClass.prototype.log = function() {
console.log(this.args);
}
var mock1 = buildInstance(MockClass, [1,2]);
mock1.log(); // [1,2]
var mock2 = buildInstance(MockClass, [1,2,3]);
mock2.log(); // [1,2,3]
it works!
利用Function.prototype泛化
作为一个肯动脑筋的程序员,我觉得还能再进一步,这个方法添加到Function.prototype
Function.prototype.buildInstance = function(args) {
var proto = projection(this.prototype);
this.apply(proto, args);
return proto;
};
然后我们就可以这样调用了
var mock1 = MockClass.buildInstance([1,2]);
mock1.log(); // [1,2]
var mock2 = MockClass.buildInstance([1,2,3]);
mock2.log(); // [1,2,3]
太赞了!
分享到:
相关推荐
当一个对象被初始化为另一个已存在的同一类对象的副本时,拷贝构造函数会被调用。它负责深拷贝或浅拷贝对象的所有成员。 7. 运算符重载 C++允许我们为现有的运算符赋予新的含义,以适应类的需求。例如,我们可以...
- **定义**:new用于在堆上分配内存并调用构造函数;delete用于释放由new分配的内存并调用析构函数。 - **应用场景**: - 在需要动态分配内存时使用new; - 释放内存时使用相应的delete。 - **注意事项**: - new...
- **构造函数与析构函数**:识别构造函数的一个常见方法是在类实例化后立即调用的函数。而析构函数通常在对象生命周期结束前被调用。 ##### B. 识别类 - **类的识别**:识别类的关键在于找到类的定义及其成员。...
`apply`的一个优势在于可以动态地传递参数,即使参数数量未知,只需将参数放入数组即可: ```javascript function g(object, func, argsArray) { func.apply(object, argsArray); } var o = {x : 15}; var f1 = ...
- **参数的规则**:参数的数量和类型应该经过精心设计,避免过多的参数使得函数调用变得复杂。 - **返回值的规则**:明确函数的返回值意义,并确保返回值与函数的功能一致。 - **函数内部实现的规则**:保持函数内部...
- 拷贝构造函数通常接收一个同类型对象的引用作为参数,用于创建新对象的副本。 16. **派生类与基类对象的关系**: - 派生类的对象可以赋值给基类的对象,可以初始化基类的引用,其地址也可以赋给指向基类的指针...
31. **转换构造函数**:具有转换功能的构造函数可以只有一个参数,用于将该类型转换为当前类类型。 32. **多继承构造函数执行顺序**:多继承时,派生类构造函数的执行顺序依赖于定义时基类的顺序。 33. **C++特性*...
- **构造和析构的次序**:解释构造函数和析构函数调用顺序的影响因素。 - **类String示例**:通过具体实例说明构造函数和析构函数的应用。 - **拷贝构造函数与赋值函数的重要性**:强调正确实现拷贝构造函数和赋值...
**解决方案**: 确认构造函数调用时提供了所有必需的参数。 #### 错误 CS0121 **描述**: 方法重载时参数匹配失败。 **解决方案**: 调整参数列表以匹配正确的重载方法。 #### 错误 CS0122 **描述**: 成员访问受限。 ...
- 实参可以是常量、变量或表达式,但在调用函数时,必须确保实参的数量和类型与形参相匹配。 - 形参不能是常量,因为它们需要用来接收实参的值。 - 形参和实参的类型和个数必须一致,除非使用了类型转换或者函数...
2. **`arguments`对象**:允许函数访问传入的所有参数,即使参数数量未知。 3. **`callee`与`caller`属性**:`callee`属性可用于递归调用,而`caller`属性则可以获取调用当前函数的父函数。 4. **`apply`与`call`...
例如,在生产计划问题中,目标函数是max f=70x1+120x2,约束条件包括9x1+4x2≤3600等,我们可以设置相应的参数调用`linprog`来找到最优生产数量x1和x2。 对于投资问题和运输问题,也可以类似地构建目标函数和约束...
正确答案是D,尽管实际上题目中的类构造函数只接受一个参数,这里提供了一个额外的参数,但从题目描述来看,应该是希望考察构造函数的调用方式。 4. **类的访问控制修饰符** - 正确答案: B.final - **知识点**:...
- **`vararg`参数**:表示可变参数列表,允许调用者传递任意数量的参数。 - **`infix`关键字**:用于定义可使用操作符语法调用的函数。 **3.5 使用字符串和正则表达式** - **字符串模板**:Kotlin支持使用`${}`...
这在处理具有可变数量或未知数量输入的函数时非常有用。 3. **谷歌街景服务**: 谷歌街景服务是Google Maps API的一部分,提供了获取全球各地高清街景图像的能力。通过该服务,开发者可以集成街景图像到自己的应用...
总结来说,`this`关键字在Java中起着至关重要的作用,它可以帮助我们清晰地表示当前对象的引用,特别是在处理重名变量、调用构造函数、返回当前对象以及在内部类中引用外部类成员时。正确理解和使用`this`能够提升...
`*args`接收一个元组,`**kwargs`接收一个字典,这样函数就能处理未知数量的参数。 Python是区分大小写的,因此变量名、函数名等标识符的大小写必须保持一致。Python的标识符命名规则规定,标识符必须以字母或...
- **选项D**:构造函数可以带有参数。这些参数用于给新创建的对象提供初始值。 #### 题目2:预处理器指令`#region`和`#endregion` - **选项A**:`#region`和`#endregion`不是用来注释代码,而是用于标记一段代码...
- 对于内置类型,`new`分配的内存默认不会初始化,而类类型对象会调用默认构造函数进行初始化。 - 初始化动态分配的对象可以使用括号或花括号,如`new int(5)`或`new int{5}`。 总的来说,动态内存管理是C++编程中...