引用
对象通过引用来传递,它们永远不会被拷贝。
var a = {
name: 'a'
}
var b = a
b.name = 'b'
console.log(a.name) // b
这里牵扯出 JavaScript 深拷贝和浅拷贝的问题
上例是浅拷贝
深拷贝见下:
var deepCopy= function(source) {
var result={};
for (var key in source) {
result[key] = typeof source[key]===’object’? deepCoyp(source[key]): source[key];
}
return result;
}
此时 var b = deepCopy(a)
得到的 b
就和 a
没有引用关系,即修改 b
不会影响 a
了
创建一个对象时,可以选择某个对象作为它的原型:
var o = {o1:1,o2:function(){alert(1)}}
function F(){}
F.prototype = o
var f = new F()
一个函数被保存为对象的一个属性时,即为一个方法。当一个方法被调用时,this
被绑定到该对象。
var dog = {
name : 'xxx' ,
leg:{
sum : 4 ,
move:function(){
console.log(this) ; //Object,是leg对象,而不是dog对象,下面证明了
alert(this.name) ; //underfined
alert(this.sum) ; //4
}
}
}
dog.leg.move();
call:
var dog = {
leg : 4 ,
color:'yellow'
}
var color = 'red' ;
function t(){
alert(this.color) ;
}
t(); // red , 因为指向this在函数中调用指向window
t.call(dog); //yellow , 把t()的作用域指向了dog
try catch 能捕捉throw抛出的异常
function add(a,b){
if(typeof a!=='number' || typeof b!=='number'){
throw {
name: 'TypeError',
message: 'add needs numbers'
}
}
return a + b;
};
function a(){
try{
add('1',3);
}catch(e){
console.log(e.name)
console.log(e.message)
}
}
a();
给类型增加方法:
Number.prototype.integer = function(){
return Math[this < 0 ? 'ceiling' : 'floor'](this) //this指向实例
}
var num = 10/3
console.log(num.integer()) ; // 3
var o = (function(){
var val = 0;
return {
addVal: function(){
val += 1
},
getVal: function(){
console.log(val)
}
}
})()//val外部不能访问,闭包
判断是否是数组或对象:
var is_array = function(value){
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'))
}
var toString = Object.prototype.toString
function isObject(obj) {
return toString.call(obj) === "[object Object]"
}
function isString(obj) {
return toString.call(obj) === "[object String]"
}
function isArray(obj) {
return toString.call(obj) === "[object Array]"
}
function isFunction(obj) {
return toString.call(obj) === "[object Function]"
}
var foo = {
bar: '你好',
func: function () {
alert(this.bar);
}
},
bar = foo.func;
bar();
/*
* 答案:function () { alert(this.bar) }
* 把foo.func函数赋值给全局变量bar然后执行,这等价于执行全局函数。全局函数的this是指向window的,
* 所以alert(this.bar)等于alert(window.bar),也就是alert函数自身。
*/
var a = 10;
a.pro = 10;
console.log(a.pro + a);
var s = 'hello';
s.pro = 'world';
console.log(s.pro + s);
/*
* 答案: NaN undefinedhello
* 给基本类型数据加属性不报错,但是引用的话返回undefined,10+undefined返回NaN,
* 而undefined和string相加时转变成了字符串。
*/
奇淫技巧
货币快速换算
var s = '1234567.89';
parseFloat(s).toLocaleString(); // 1,234,567.89
s.replace(/(d)(?=(?:d{3})+(?:.|$))/g, '$1,'); // 1,234,567.89
向下取整Math.floor,可以用|0,可以用~~,也可以用右移符>>代替。
var a= 1.2|0; // 1
var a = ~~1.2; // 1 (比Math.floor快4倍左右)
var a = 1.2>>0; // 1
/* 但是两者最好都只用在正整数上,因为只是舍掉了小数部分。Math.floor(-1.2)应该为-2,这两种方法的结果为-1 */
用( new Function(stringCode) )()比eval快50倍。
转数字用+
var a = +'1234'; // 1234
合并数组
var a = [1,2,3];
var b = [4,5,6];
Array.prototype.push.apply(a, b);
console.log(a); // [1,2,3,4,5,6]
交换值
a = [b, b=a][0];
快速取数组最大和最小值
Math.max.apply(Math, [1,2,3]); // 3
Math.min.apply(Math, [1,2,3]); // 1
运算符-->叫做趋向于,可以声明一个变量 然后让他 趋向于 另一个数。
var x = 10; while (x --> 0)console.log(x);
// 9,8,7,6,5,4,3,2,1,0