-
-
Notifications
You must be signed in to change notification settings - Fork 893
Open
Description
(function () {
function PROPERTY(CLASS, name, descriptor) {
// 确保至少提供了一个 get 或 set 方法
if (!descriptor.get && !descriptor.set) {
throw new Error(
sprintf(
"PROPERTY: At least one of 'get' or'set' must be provided for property '%s'.\nExample: descriptor = { get: function() { return this._value; } };",
name
)
);
}
// // 定义属性
// Object.defineProperty(CLASS.prototype, name, attr);
var attr = {
enumerable: true, // 属性可枚举
configurable: true,// 属性可配置
get: descriptor.get || undefined,
set: descriptor.set || undefined
};
Object.defineProperty(CLASS.prototype, name, attr);
}
// 测试用例
function Person() {
this._name = "John";
this._age = 25;
}
PROPERTY(Person, "name", {
get: function() {
return this._name;
},
// set: function(value) {
// this._name = value;
// }
});
var p = new Person();
console.log(p.name); // John
// p.name = "Mary";
// console.log(p.name); // Mary
})();
运行这段代码时,当get或set有一个为Undefined时,会报错。
在运行 05.属性jsfl 时,发生以下JavaScript 错误:
第425 行(在"es5-sham.jsfl"文件中):
SyntaxError: invalid setter usage
对应代码
es5-sham.jsfl
var binder = function () {
if (this instanceof bound) {
// 15.3.4.5.2 [[Construct]]
// When the [[Construct]] internal method of a function object,
// F that was created using the bind function is called with a
// list of arguments ExtraArgs, the following steps are taken:
// 1. Let target be the value of F's [[TargetFunction]]
// internal property.
// 2. If target has no [[Construct]] internal method, a
// TypeError exception is thrown.
// 3. Let boundArgs be the value of F's [[BoundArgs]] internal
// property.
// 4. Let args be a new list containing the same values as the
// list boundArgs in the same order followed by the same
// values as the list ExtraArgs in the same order.
// 5. Return the result of calling the [[Construct]] internal
// method of target providing args as the arguments.
var result = apply.call(
target,
this,
array_concat.call(args, array_slice.call(arguments))
);
if ($Object(result) === result) {
return result;
}
return this;
}
// 15.3.4.5.1 [[Call]]
// When the [[Call]] internal method of a function object, F,
// which was created using the bind function is called with a
// this value and a list of arguments ExtraArgs, the following
// steps are taken:
// 1. Let boundArgs be the value of F's [[BoundArgs]] internal
// property.
// 2. Let boundThis be the value of F's [[BoundThis]] internal
// property.
// 3. Let target be the value of F's [[TargetFunction]] internal
// property.
// 4. Let args be a new list containing the same values as the
// list boundArgs in the same order followed by the same
// values as the list ExtraArgs in the same order.
// 5. Return the result of calling the [[Call]] internal method
// of target providing boundThis as the this value and
// providing args as the arguments.
// equiv: target.call(this, ...boundArgs, ...args)
return apply.call(
target,
that,
array_concat.call(args, array_slice.call(arguments)) // 425
);
};
所以,我的解决方案是
es5-shim.jsfl
if (!Object.defineProperty || definePropertyFallback) {
var ERR_NON_OBJECT_DESCRIPTOR = 'Property description must be an object: ';
var ERR_NON_OBJECT_TARGET = 'Object.defineProperty called on non-object: ';
var ERR_ACCESSORS_NOT_SUPPORTED =
'getters & setters can not be defined on this javascript engine';
var ERR_VALUE_NOT_ALLOWED = "Invalid property descriptor. Cannot both specify accessors and a value or writable attribute."
Object.defineProperty = function defineProperty(object, property, descriptor) {
// 检查是否同时包含值属性和访问器属性
if (('value' in descriptor || 'writable' in descriptor) && ('get' in descriptor || 'set' in descriptor)) {
throw new TypeError(ERR_VALUE_NOT_ALLOWED);
}
if (isPrimitive(object)) {
throw new TypeError(ERR_NON_OBJECT_TARGET + object);
}
if (isPrimitive(descriptor)) {
throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
}
// 如果 get 或 set 为 undefined,则移除它们
if ('get' in descriptor && typeof descriptor.get !== 'function') {
delete descriptor.get;
}
if ('set' in descriptor && typeof descriptor.set !== 'function') {
delete descriptor.set;
}
也就是在执行这个函数之前对descriptor进行判断,提前把get与set处理好。
同时做出了优化,当write与get set同时存在时将会报错。这与node JS的行为相同。
这个可能是 bind方法,与原生方法的行为不同的导致的bug。
希望可以采纳
Metadata
Metadata
Assignees
Labels
No labels