如何判断方法的所属对象
hasOwnProperty:
console.log({}.hasOwnProperty);
//function hasOwnProperty() { [native code] }
console.log(Object.hasOwnProperty);
//function hasOwnProperty() { [native code] }
console.log({}.defineProperties);
//undefined
console.log(Object.defineProperties);
// function defineProperties() { [native code]
可以分别用实例和构造器调用方法
- 若方法在实例上,则此方法必定在构造器上
- 若方法在构造器上,此方法不一定在原型上
控制台打印的方法有的是灰色的?
1. 直接将属性定义在{}中:
可见自定义属性key1是深色中,而指向原型对象的对象proto是灰色的;
2. 用Object.defineProperty()定义属性
此时看到key1是亮色,而自定义的key2也是灰色,why?
打印出key1,key2两个属性的的描述器后发现:
- 用{}定义的属性的描述中,writable、enumerable、configurable都是true
- 用Object.defineProperty定义的属性中描述全为false
上图中,将enumerable属性改为true后,发现其属性值变深色了。
说明:不可枚举的属性值为浅色,即不会出现在for in中
如何判断对象是否包含某属性
用obj.key
var obj = {key:undefined};
console.log(obj.key);//undefined
console.log(obj.noname);//undefined
然而key是obj的属性,因此上面方法不可行
用Object.hasOwnProperty
var obj = {key:undefined};
console.log(Object.hasOwnProperty(obj,key));//true
console.log(Object.hasOwnProperty(obj,noname));//false
然而当hasOwnProperty方法被重写时就要注意了:
var obj = {
hasOwnProperty:function(){
return false;
},
hello:123
};
obj.hasOwnProperty('hello');//false
应该使用:
({}).hasOwnProperty.call(obj,'hello');//true
某些方法两边有私有属性的标志,如__proto__
这些方法作者的本意不想让用户调用,但是js中所有方法都是可以调用的,那么肯定有其他更好的方法来调用这些私有方法
例如obj.__defineGetter__
,此方法不推荐直接使用:
obj.__defineGetter__('key1',function(){return 'value1'});
console.log(obj.key1)//'value1'
可以使用以下两个标准方法替代
1.
var obj = {get key1(){return 1},get key2(){return 2}}
2.
Object.defineProperty(obj,"value1",{
get:function(){return 1;}
})
数组length属性
var arr = [1,2,3];
arr.length = 6;
console.log(arr);//[1,2,3,undefined*3]
5 in arr; //false
arr[5] = undefined;
5 in arr; //true
undefined定义不会被覆盖
因为全局undefined只是保存了undefined实际类型的副本
setTimeout中this指向全局
function Foo() {
this.value = 42;
this.method = function() {
// this 指向全局对象
console.log(this.value); // 输出:undefined
};
setTimeout(this.method, 500);
}
new Foo();
setInterval方法优化
function foo(){
// 阻塞执行 1 秒
}
setInterval(foo, 100);
此时会有10个待执行的foo堆积下来,因此可在setInterval内部使用setTimeout:
function foo(){
// 阻塞执行 1 秒
setTimeout(foo, 100);
}
foo();
隐藏使用的eval函数
由于setTimeout中第一个参数若为function,则其内this指向全局,而第一个参数若为字符串,则相当于隐式的eval:
function foo() {
// 将会被调用
}
function bar() {
function foo() {
// 不会被调用
}
setTimeout('foo()', 1000);
}
bar()