一 对象
1—
console.log(false.toString()); //false
console.log([1,2,3].toString()); //1,2,3
function Foo(){ }
Foo.bar=1;
console.log(Foo.bar);//1
//console.log(2..toString());//报错
console.log(2..toString());//2
console.log(2 .toString());//2
console.log((2).toString());//2
//变通方法可以让数字的字面量看起来像对象
2—
var foo={name: 'kitten'} console.log(foo.name);//kitten console.log(foo['name']);//kitten var get='name'; console.log(foo[get]);//kitten //console.log(foo.1234);//报错 console.log(foo['1234']);//undefined
3—
var obj={
bar:1,
foo:2,
baz:3
};
obj.bar=undefined;
obj.foo=null;
delete obj.baz;
for(var i in obj){
if(obj.hasOwnProperty(i)){
console.log(i, ''+obj[i]);
}
}
//输出:
//bar undefined
//foo null
4—hasOwnProperty函数
为了判断一个对象是否包含自定义属性而不是原型链上的属性,可以使用继承自Objeect.prototype的hasOwnProperty方法。其是JavaScript中唯一一个处理属性但是不查找原型链的函数。
5—for in 循环
在查找对象属性时遍历原型链上的所有属性。
Object.prototype.bar=1; var foo= {moo:2}; for(var i in foo){ console.log(i); //moo bar }
for(var i in foo) { if (foo.hasOwnProperty(i)) { console.log(i);//moo } }
二 函数
1— this
Foo.method = function() { function test() { // this 将会被设置为全局对象(译者注:浏览器环境中也就是 window 对象) } test(); }
Foo.method = function() { var that = this; //为了在 test 中获取对 Foo 对象的引用,我们需要在 method 函数内部创建一个局部变量指向 Foo 对象。 function test() { // 使用 that 来指向 Foo 对象 } test(); }
2--循环中的闭包
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i);//输出10 十次 }, 1000); } //ps:当 console.log 被调用的时候,匿名函数保持对外部变量 i 的引用,此时 for循环已经结束, i 的值被修改成了 10. for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, 1000);//输出0到9 })(i); } //ps:自执行匿名函数。外部的匿名函数会立即执行,并把 i 作为它的参数,此时函数内 e 变量就拥有了 i 的一个拷贝。
//当传递给 setTimeout 的匿名函数执行时,它就拥有了对 e 的引用,而这个值是不会被循环改变的。 for(var i = 0; i < 10; i++) { setTimeout((function(e) { //从匿名函数返回一个函数 return function() { console.log(e); } })(i), 1000) }
3— arguments对象
函数中的参数列表,实际上是一个对象。
转换为数组方法:
(1) Array.prototype.slice.call(arguments); (性能欠佳)
(2)下面是将参数从一个函数传递到另一个函数的推荐做法。function foo() { bar.apply(null, arguments); } function bar(a, b, c) { // 干活
}
(3)另一个技巧是同时使用 call 和 apply,创建一个快速的解绑定包装器。function Foo() {} Foo.prototype.method = function(a, b, c) { console.log(this, a, b, c); }; // 创建一个解绑定的 "method" // 输入参数为: this, arg1, arg2...argN Foo.method = function() { // 结果: Foo.prototype.method.call(this, arg1, arg2... argN) Function.call.apply(Foo.prototype.method, arguments); }; / Foo.method = function() { var args = Array.prototype.slice.call(arguments); Foo.prototype.method.apply(args[0], args.slice(1)); };
4—构造函数
function Foo() { this.bla = 1; } Foo.prototype.test = function() { console.log(this.bla); }; var test = new Foo();//this指向新创建的对象 test.test();//1 //ps:被调用的函数没有显示的return表达式,则隐式的返回this
function Bar() { return 2; } console.log( new Bar().constructor === Bar) //true console.log(new Bar()); // 返回新创建的对象 ,Bar {}
function Test() { this.value = 2; return { foo: 1 }; } console.log(new Test()); // 返回的对象,{ foo: 1 } console.log((new Test()).value === undefined);//true console.log((new Test()).foo === 1);//true
function Bar() { return new Number(2); } console.log(new Bar().constructor === Number);//true console.log(new Bar()); // [Number: 2]
function Foo() { this.bla = 1; // 获取设置全局参数 } console.log(Foo()); // undefined
function Bar() { var value = 1; return { method: function() { return value; } } } Bar.prototype = { foo: function() {} }; console.log(new Bar());//{ method: [Function: method] } console.log(Bar());//{ method: [Function: method] }
三 数组
1 数组遍历与属性
数组遍历推荐for循环,在使用for循环时可以将数组长度缓存在一个局部变量里,减小性能开销。
ps:for in循环会枚举原型链上的所有属性,需通过hasOwnProperty函数过滤,会比普通的for循环慢。
ps:推荐使用数组字面量进行创建数组。
四 类型
1 比较
等于比较:
console.log("" == "0" ) // false console.log(0 == "" ) // true console.log(0 == "0") // true console.log(false == "false" ) // false console.log(false == "0" ) // true console.log(false == undefined ) // false console.log(false == null) // false console.log(null == undefined) // true console.log(" " == 0 ) // true
恒等比较:
console.log("" === "0"); // false console.log(0 === "" ); // false console.log(0 === "0"); // false console.log(false === "false"); // false console.log(false === "0"); // false console.log(false === undefined); // false console.log(false === null); // false console.log(null === undefined); // false console.log(" " === 0); // false
比较对象:只有同一个对象的同一个实例才被认为是相等的
console.log(); console.log({} === {}); // false console.log(new String('foo') === 'foo'); // false console.log(new Number(10) === 10); // false var foo = {}; console.log(foo === foo); // true
ps:推荐使用严格等于操作符。如果类型需要转换,应该在比较之前显式的转换, 而不是使用语言本身复杂的强制转换规则。
Ps:为了检测一个对象的类型,推荐使用 Object.prototype.toString 方法
Ps:instanceof 操作符应该仅仅用来比较来自同一个 JavaScript 上下文的自定义对象。
2 类型转换
转换为字符串
'' + 10 === '10'; // true
ps:将一个值加上空字符串可以轻松转换为字符串类型。
转换为数字
+'10' === 10; // true
ps:用一元的加号操作符,可以把字符串转换为数字。
//字符串转换为数字的常用方法:
console.log(+'010' === 10);//true console.log(Number('010') === 10);//true console.log(parseInt('010', 10) === 10); // 用来转换为整数//true
console.log(+'010.2' === 10.2);//true console.log(Number('010.2') === 10.2);//true console.log(parseInt('010.2', 10) === 10);//true
转换为布尔型通过使用 否 操作符两次,可以把一个值转换为布尔型。
!!'foo'; // true !!''; // false !!'0'; // true !!'1'; // true !!'-1' // true !!{}; // true !!true; // true
参考 & 学习 & 感谢 http://bonsaiden.github.io/JavaScript-Garden/zh/#function.constructors