一 对象
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(" \t\r\n" == 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(" \t\r\n" === 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