lee*_*d00 17 javascript oop object-literal
有没有办法在Javascript中确定对象是使用object-literal表示法还是使用构造函数方法创建的?
在我看来,你只是访问它的父对象,但如果你传入的对象没有引用它的父对象,我认为你不能告诉它,你呢?
Jes*_*sse 14
你想要的是:
Object.getPrototypeOf(obj) === Object.prototype
Run Code Online (Sandbox Code Playgroud)
此检查该对象是与任一创建一个普通的对象new Object()或{...},而不是一些子类Object。
Ric*_*ick 12
我刚刚在一个甜蜜的hackfest中遇到了这个问题和线程,其中涉及一个圣杯任务,用于评估一个对象是用{}还是新的Object()创建的(我还是没想到它.)
无论如何,我很惊讶地发现这里发布的isObjectLiteral()函数和我为Pollen.JS项目编写的我自己的isObjLiteral()函数之间的相似性.我相信这个解决方案是在我的Pollen.JS提交之前发布的,所以 - 对你说!我的好处是长度......不到一半(包括你的设置例程),但两者产生相同的结果.
看一看:
function isObjLiteral(_obj) {
var _test = _obj;
return ( typeof _obj !== 'object' || _obj === null ?
false :
(
(function () {
while (!false) {
if ( Object.getPrototypeOf( _test = Object.getPrototypeOf(_test) ) === null) {
break;
}
}
return Object.getPrototypeOf(_obj) === _test;
})()
)
);
}
另外,一些测试内容:
var _cases= {
_objLit : {},
_objNew : new Object(),
_function : new Function(),
_array : new Array(),
_string : new String(),
_image : new Image(),
_bool: true
};
console.dir(_cases);
for ( var _test in _cases ) {
console.group(_test);
console.dir( {
type: typeof _cases[_test],
string: _cases[_test].toString(),
result: isObjLiteral(_cases[_test])
});
console.groupEnd();
}
或者在jsbin.com上......
当你到达那里时一定要打开萤火虫 - 调试文件是为IE爱好者.
Eli*_*rey 11
编辑:我解释"对象常量"作为使用对象文本创建任何东西或在Object构造函数.这就是John Resig最有可能的意思.
我有一个功能,即使.constructor被污染或者对象是在另一个框架中创建的,它也能工作.请注意Object.prototype.toString.call(obj) === "[object Object]"(有些人可能认为)不能解决这个问题.
function isObjectLiteral(obj) {
if (typeof obj !== "object" || obj === null)
return false;
var hasOwnProp = Object.prototype.hasOwnProperty,
ObjProto = obj;
// get obj's Object constructor's prototype
while (Object.getPrototypeOf(ObjProto = Object.getPrototypeOf(ObjProto)) !== null);
if (!Object.getPrototypeOf.isNative) // workaround if non-native Object.getPrototypeOf
for (var prop in obj)
if (!hasOwnProp.call(obj, prop) && !hasOwnProp.call(ObjProto, prop)) // inherited elsewhere
return false;
return Object.getPrototypeOf(obj) === ObjProto;
};
if (!Object.getPrototypeOf) {
if (typeof ({}).__proto__ === "object") {
Object.getPrototypeOf = function (obj) {
return obj.__proto__;
};
Object.getPrototypeOf.isNative = true;
} else {
Object.getPrototypeOf = function (obj) {
var constructor = obj.constructor,
oldConstructor;
if (Object.prototype.hasOwnProperty.call(obj, "constructor")) {
oldConstructor = constructor;
if (!(delete obj.constructor)) // reset constructor
return null; // can't delete obj.constructor, return null
constructor = obj.constructor; // get real constructor
obj.constructor = oldConstructor; // restore constructor
}
return constructor ? constructor.prototype : null; // needed for IE
};
Object.getPrototypeOf.isNative = false;
}
} else Object.getPrototypeOf.isNative = true;
Run Code Online (Sandbox Code Playgroud)
这是测试用例的HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<!-- Online here: http://code.eligrey.com/testcases/all/isObjectLiteral.html -->
<title>isObjectLiteral</title>
<style type="text/css">
li { background: green; } li.FAIL { background: red; }
iframe { display: none; }
</style>
</head>
<body>
<ul id="results"></ul>
<script type="text/javascript">
function isObjectLiteral(obj) {
if (typeof obj !== "object" || obj === null)
return false;
var hasOwnProp = Object.prototype.hasOwnProperty,
ObjProto = obj;
// get obj's Object constructor's prototype
while (Object.getPrototypeOf(ObjProto = Object.getPrototypeOf(ObjProto)) !== null);
if (!Object.getPrototypeOf.isNative) // workaround if non-native Object.getPrototypeOf
for (var prop in obj)
if (!hasOwnProp.call(obj, prop) && !hasOwnProp.call(ObjProto, prop)) // inherited elsewhere
return false;
return Object.getPrototypeOf(obj) === ObjProto;
};
if (!Object.getPrototypeOf) {
if (typeof ({}).__proto__ === "object") {
Object.getPrototypeOf = function (obj) {
return obj.__proto__;
};
Object.getPrototypeOf.isNative = true;
} else {
Object.getPrototypeOf = function (obj) {
var constructor = obj.constructor,
oldConstructor;
if (Object.prototype.hasOwnProperty.call(obj, "constructor")) {
oldConstructor = constructor;
if (!(delete obj.constructor)) // reset constructor
return null; // can't delete obj.constructor, return null
constructor = obj.constructor; // get real constructor
obj.constructor = oldConstructor; // restore constructor
}
return constructor ? constructor.prototype : null; // needed for IE
};
Object.getPrototypeOf.isNative = false;
}
} else Object.getPrototypeOf.isNative = true;
// Function serialization is not permitted
// Does not work across all browsers
Function.prototype.toString = function(){};
// The use case that we want to match
log("{}", {}, true);
// Instantiated objects shouldn't be matched
log("new Date", new Date, false);
var fn = function(){};
// Makes the function a little more realistic
// (and harder to detect, incidentally)
fn.prototype = {someMethod: function(){}};
// Functions shouldn't be matched
log("fn", fn, false);
// Again, instantiated objects shouldn't be matched
log("new fn", new fn, false);
var fn2 = function(){};
log("new fn2", new fn2, false);
var fn3 = function(){};
fn3.prototype = {}; // impossible to detect (?) without native Object.getPrototypeOf
log("new fn3 (only passes with native Object.getPrototypeOf)", new fn3, false);
log("null", null, false);
log("undefined", undefined, false);
/* Note:
* The restriction against instantiated functions is
* due to the fact that this method will be used for
* deep-cloning an object. Instantiated objects will
* just have their reference copied over, whereas
* plain objects will need to be completely cloned.
*/
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
var doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write("<body onload='window.top.iframeDone(Object);'>");
doc.close();
function iframeDone(otherObject){
// Objects from other windows should be matched
log("new otherObject", new otherObject, true);
}
function log(msg, a, b) {
var pass = isObjectLiteral(a) === b ? "PASS" : "FAIL";
document.getElementById("results").innerHTML +=
"<li class='" + pass + "'>" + msg + "</li>";
}
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
听起来你正在寻找这个:
function Foo() {}
var a = {};
var b = new Foo();
console.log(a.constructor == Object); // true
console.log(b.constructor == Object); // false
Run Code Online (Sandbox Code Playgroud)
对象上的构造函数属性是指向用于构造它的函数的指针.在上面的例子中b.constructor == Foo.如果对象是使用大括号(数组文字符号)创建的,或者使用new Object()它的构造函数属性== Object.
更新: crescentfresh指出,$(document).constructor == Object而不是等于jQuery构造函数,所以我做了一点挖掘.似乎通过使用对象文字作为对象的原型,您渲染构造函数属性几乎一文不值:
function Foo() {}
var obj = new Foo();
obj.constructor == Object; // false
Run Code Online (Sandbox Code Playgroud)
但:
function Foo() {}
Foo.prototype = { objectLiteral: true };
var obj = new Foo();
obj.constructor == Object; // true
Run Code Online (Sandbox Code Playgroud)
还有就是这个在另一个答案很好的解释在这里,和更为复杂的解释在这里.
我认为其他答案是正确的,并没有真正的方法来检测这一点.