1、匿名函数从语法上叫函数直接量,JavaScript语法需要包围匿名函数的括号,事实上自调用匿名函数有两种写法:
(function() {
console.info( this );
console.info( arguments );
}( window ) );
--------------------------------------------------------------------------
(function() {
console.info( this );
console.info( arguments );
})( window );
经测试:不是匿名函数也是可以的。
2、函数名前有一元操作符
- +function(){}();
这里的加号,也可以替换成!,~,-等其他一元操作符,其效果相当于:
- (function() { console.log("Foo!"); })();
- // or
- (function() { console.log("Foo!"); }());
如果没有这个加号的话,解析器会认为function是一个函数声明的开始,而后面()将会导致语法错误。在function前面加上+号时,就变成了一个函数表达式,而函数表达式后面又添加了一个()就变成了一个立即执行的函数了。
3、JavaScript 的字符串是不可变的(immutable),String 类定义的方法都不能改变字符串的内容。像 String.toUpperCase() 这样的方法,返回的是全新的字符串,而不是修改原始字符串。
4、如下代码
<script type="text/javascript">
a = function ddd( ) {alert(1)}
alert(a.name)
a()
a = function fff( ) {alert(2)}
alert(a.name)
a() ddd()
</script>
结果为:ddd,1,fff, 2,错误(ddd未定义)
另说明 js语句可以不用分号;结尾
5、如下代码
if(0) {
alert(1);
}
if(0.0) {
alert(2);
}
if(NaN) {
alert(3);
}
if(false) {
alert(4);
}
if(null) {
alert(5);
}
if(undefined) {
alert(6);
}
if("") {
alert(7);
}
if([]) {
alert(8);
}
if({}) {
alert(9);
}
if(function(){}) {
alert(10);
}
输出 8,9,10 和php不同,php中好像空对象,空数组也是false,这里他们是复合数据类型,代表了地址。
js基本数据类型: number, string, boolean
复合数据类型:对象,数组,函数
其他:null, undefined
6、如下代码
function test(a) {
alert(a == null); //true
alert(a == undefined); //true
alert(a === null); //false
alert(undefined == null); //true
alert(a === undefined); //true
alert(typeof a); //undefined
alert(typeof null == "object"); //true
alert(typeof [] == "object"); //true
var s = "fdf";
alert(typeof s == "string"); //true
var s = new String("fdf"); //不会报重定义错误
alert(typeof s == "object"); //true
}
test();
7、如下代码
if(NaN === NaN) {
alert(1);
}
if(Infinity === Infinity) {
alert(2);
}
if(null === null) {
alert(3);
}
if(undefined === undefined) {
alert(4);
}
if("" === "") {
alert(5);
}
只有NaN !== 自己
8、深度复制
function cp(object) {
var obj = {};
for(var i in object) {
if(typeof object[i] === "object") {
obj[i] = cp(object[i]);
} else {
obj[i] = object[i];
}
}
return obj;
}
var a = {1:{2:3,4:5}, 2:"sdfd", 3:{"a":3, "d":"e"}};
var b = cp(a);
console.log(b);
9、另一种深度复制
function cp(obj) {
var map = new Map();
function copy(object){
var _object = map.get(object);
if(_object) {
return _object;
}
_object = {};
map.put(object, _object);
for(var i in object) {
if(object.hasOwnProperty(i)) {
var d = object[i];
if(d && typeof d === "object") {
_object[i] = copy(d);
} else {
_object[i] = d;
}
}
}
return _object;
}
return copy(obj);
}
//Test 1
var c = {"name":"qhairen"};
var a = {1 : c, 2 : "sdfd", 3 : c};
alert(a["1"] == a["3"]);
var b = cp(a);
console.log(b);
alert(b["1"] == b["3"]);
//Test 2
var c = {"name":null};
var d = {"age": c};
c.name = d;
console.log(c);
alert(c == c.name.age);
var e = cp(c);
console.log(e);
alert(e == e.name.age);
=====================Map的代码见另一篇文章: JS中的Map简单实现
10、js中,new操作符的工作原理
- 新建一个对象,instance = new Object();
- 设置原型链,instance.__proto__ = F.prototype;
- 让F中的this指向instance,执行F的函数体
- 判断F的返回值类型:
function G() {
this.age = 26;
}
function F() {
this.name = "qhairen";
// return 1;
// return 1.2;
// return true;
// return "dsfds";
// return null;
// return undefined;
// return this;
// return NaN;
// return Infinity; //上面全部返回F对象
// return [1, 2, 3]; //返回数组
// return new G(); //返回G对象
// return function(){alert(1);}; //返回函数
}
var f = new F();
console.dir(f);
console.assert(!f.hasOwnProperty("constructor"));
console.assert(F.prototype.hasOwnProperty("constructor"));
console.assert(G.prototype.hasOwnProperty("constructor"));
console.assert(G.prototype.constructor === G);
F.prototype = new G();
var f = new F();
console.dir(f);
F.prototype = new G();
alert(f instanceof F); //false
alert(f.__proto__ === F.prototype); //false
console.dir(F.prototype);
var f = new F();
alert(f instanceof F); //true
alert(f.__proto__ === F.prototype); //true
console.dir(F.prototype);
11、js中var o = f();和var o = new f();的区别?
var o = new f();
相当于
var o1 = Object.create(f.prototype);
var r = f.call(o1);
var o = (_.isObject(r) ? r : o1);
而普通的函数调用var o = f();通常o会得到undefined而且属性会写到window上去。