javascript 权威指南:
1)XHTML区分大小写;
2)javascript 代码两行之间可以不加入分号,会默认插入;
3)isNaN():是否不是数字,NaN和任何值都不相等
4)数字转字符串T:
var num=17; console.log(typeof (num+"")=="string");//true
var num=17;console.log("0x"+nun.toString(16));//0x11
5)字符串转换为数字T:
var num="20"*"2";console.log(num);//40
var num="20"-0;console.log(typeof num);//number
var num="11aa"-0;console.log(num);//NaN
console.log(typeof NaN);//number
6)var num={"name":"jj","sex":"male"};console.log(num.toString());//[object Object]
7)
数字环境null=0:var num=null+2;console.log(num);//2
布尔环境null=false:var num=null&&true;console.log(num);
var s1="hello world";
var s2=s1.substring(0,2);
此句的伪代码为:
var s1=new String("hello world");//创建String 类型的一个实例
var s2=s1.substring(0,2);//通过实例调用指定方法
s1=null;//销毁这个实例
从上我们可以总结下 引用类型和基本包装类型的区别:
a)使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前一直保持在内存中,
而自动创建的包装类对象,只存在于一行代码的执行瞬间,然后立即被销毁。因此,我们不能在运行时为基本
包装类型添加属性和方法。
console.log(typeof (new Date()));//object
var s1=new String("hello world");
var s2="hello world";
console.log(typeof s2);//string
if(s1){
console.log("基本包装类型对象在布尔环境中都会转换为布尔值true");
}
再来看看Boolean类型
var falseObj=new Boolean(false);
var res=falseObj&&true;
console.log(res);//true
console.log(falseObj instanceof Boolean);//true
console.log(falseObj instanceof Object);//true
不管何时,非空对象用在布尔环境中的时候,都转换为true,对于所有对象(包括数组、函数、包装类型对象)都是成立的。
而
var falseObj=false;
var res=falseObj&&true;
console.log(res);//false
8)类型间的转换
console.log([].toString());//空字符串
console.log(["1"].toString());//string 1
console.log(["1abc","ccc"].toString());//string 1abc,ccc
console.log(new Date()+222);//得到字符串Tue Jun 04 2013 23:31:08 GMT+0800222
console.log();
9)传值和传址
复制:
1)传值: 实际复制的是值,存在两个不同的、独立的拷贝;
2)传址:复制的只是对数值的引用,如果通过这个新的引用修改了值,这个改变对最初的引用来说也可见
传递:
1)传值:传递给函数的值是一个独立的拷贝,对他的改变在函数外部没有任何影响
2)传址:传递给函数的是一个对数值的引用,如果函数通过传递给它的引用修改了值,那么这个值在外部也是可见的。
比较:
1)传值:比较的是两个独立的值;
2)传址:比较是两个引用,以判断他们引用的是否是同一个值;
javascript中规则:
基本类型值指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置;(Number/Boolean/String/Null/Undefined),占用的内存空间大小固定。
引用类型值指的是那些保持在堆内存中的对象,即变量中保存的实际上是一个指针,这个指针指向内存中的另一个位置,
这个位置保存对象;(对象、数组和函数),内存地址(指针)保存在栈内存中,查询引用的类型的变量时,首先是从栈内存中读取内存地址,然后
找到保存在堆中的值。
ECMAScript中所有函数的参数都是按值传递
看看实例:
function demo01(){
var a="hello";
var b=a;
a="world";
//此处的a确切来讲,a="world";并不是修改a,而是创建了一个新字符串(相应地,在内存中分配一块新空间),
//然后让a引用该字符串——更像是替换变量的值;原来的字符串呢?因为没有变量引用它,也就成为垃圾了(当然,垃圾所占用的内存会被回收)。
console.log(b);
console.log(a);
}
demo01();
function demo02(obj){
obj.name="hello world";
}
obj01={};
demo02(obj01);
console.log(obj01.name);//hello world
function demo03(obj){
obj.name="hello world";
obj=new Object();//此处重写obj时,这个变量的引用就是一个局部对象,局部对象在函数执行完毕后会立即销毁
obj.name="Welcome beijing";
}
obj01={};
demo02(obj01);
console.log(obj01.name);//hello world
由demo03可以看出,javascript中引用类型的函数参数传递也是按值传递的。
10)变量的作用域:
规则:
顶层作用域(window)》Object类属性的作用域》Object原型属性的作用域》var 变量所在的作用域》闭包作用域》函数作用域
javascript 中没有块级作用域
function demo04(){
var i=0;
if(typeof i =="number"){
var j=0;
for(var k=0;k<l0;k++){
console.log(k);
}
}
}
在此函数中i、j、k的作用域是相同的;它们在整个demo04函数体内都是有定义的
11)javascript 运算符:
a)i++,++i:
var i=1;
var j=++i;
//i=i+1;j=i;
console.log(i);//2
console.log(j);//2
var i=1;
var j=i++;
//j=i;i=i+1;
console.log(i);//2
console.log(j);//1
b)in:
in左边的字符串是右边对象或者数组的一个属性名,返回true,常用在对象遍历中
var arr=["aa","bbb","cccc"];
var obj={"x":"aa","y":"bb"};
console.log("x" in obj);//true
console.log("x" in Object);//false
console.log("0" in arr);//true
c)instanceof:
console.log(obj instanceof Object);//true
console.log(arr instanceof Array);//true
d)
~运算符:按位取反的操作
^:按位异或
var selector="#layout";
var pattern = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;
var match = pattern.exec( selector );
if(match&&~match[0].indexOf("#")){
var id=document.getElementById(match[2]);
console.log(match);//["#layout", undefined, "layout"]
}
原码:符号位+数值的二级制码
补码:正数的补码与原码相同,负数的补码等于其原码的符号位不变,数值部分的各位取反,然后整个数加1。
console.log(~0);//-1
console.log(~-1);//0
console.log(~2);//-3
对一个值使用~运算符,相当于改变它的符号后的值减1
var pattern=/^(zo)*$/g;
var match=pattern.exec("zozo");
console.log(match);//["zozo", "zo"]
exec()函数返回包含第一个匹配项信息的数组,如果么有匹配项返回null
数组第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串
e)void运算符:
其可以出现在任何操作数之前,这个运算符的用途比较特殊,它总是舍弃运算数的值,然后返回undefined;在实际使用中,
我们通常使用void地方在<a href="www.baidu.com" οnclick="aa()">fafdasdfasfdasfd</a>标签中,请看demo01:
i)demo01:
<!doctype html>
<html>
<body>
<a href="http://www.baidu.com" οnclick="aa()">fafdasdfasfdasfd</a>
<script type="text/javascript">
function aa(){
alert("jsdemo");
}
</script>
</body>
</html>
当点击a链接时首先触发aa()方法,弹出"jsdemo",然后跳转到baiduc.com
ii)demo02
<!doctype html>
<html>
<body>
<a href="javascript:void 1" οnclick="aa()">fafdasdfasfdasfd</a>
<script type="text/javascript">
function aa(){
alert("jsdemo");
}
</script>
</body>
</html>
demo02中只会弹出jsdemo;因为console.log(void 1);//undefined
iii)demo03:
<!doctype html>
<html>
<body>
<a href="http://www.baidu.com" οnclick="aa(event)">fafdasdfasfdasfd</a>
<script type="text/javascript">
function aa(e){
var e=e||window.event;
alert("jsdemo");
if (e && e.preventDefault) {//如果是FF下执行这个
e.preventDefault();
}else{
e.returnValue = false;//如果是IE下执行这个
}
}
</script>
</body>
</html>
demo03中只会弹出jsdemo;阻止了a标签的默认事件;
f)[]运算符:
可用来存在数组元素或者对象的属性,当遍历一个对象时是很常用的
var obj={
"x":1,
"y":"demo01",
"z":{"w":1,"u":"u"},
"w":[1,2,"cc"]
}
console.log(obj["w"]);//[1,2,"cc"]
for(f in obj){
console.log(f+"----"+obj[f]);
}
result:
x----1
y----demo01
z----[object Object]
w----1,2,cc//此时数组和字符串拼串,自动转换为字符串
12)表达式语句:
try/catch/finally:
try块中至少有一个catch块和finally块
当try和finally一起使用时,无论try块中有break、continue、return 语句,finally中的语句都会执行
如下demo01:
for (var i=0; i<3; i++){
try{
if(typeof i ==="number"){
break;
}
}finally{
i++;
console.log(i);//输出:1
}
}
for (var i=0; i<3; i++){
try{
if(typeof i ==="number"){
continue;
}
}catch(e){
console.log("error");
}finally{
i++;
console.log(i);//输出:1,3
}
}
with语句:
with(obj){
//执行代码
}
常用于扩展作用域链,能够有效地将obj添加到作用域链的头部,然后执行statement,再把作用域链回复到以前状态,
但是因使用with语句的代码很难优化,而且性能也比较低,所以一般不赞成使用
13)通用的Object属性和方法:
a)constructor
var d=new Date();
console.log(d.constructor==Date);//true
确定某个对象的类型:
var o=new Date();
if(typeof o==="object"&&o.constructor===Date){
console.log("aa");//aa
}
if(typeof o==="object"&&o instanceof Date){
console.log("aa");//aa
}
b)toString():
var str="aaa";
var obj={"name":"bbb","sex":"ccc"};
console.log(str+obj);//aaa[object Object]
alert(obj);//[object Object]
判断一个变量是否为数组:
var arr=["aa",1,"bb"];
if(Object.prototype.toString.call(arr)==="[object Array]"){
console.log(arr.join("*"));//aa*1*bb
}
c)hasOwnProperty(propertyName):
用于检查给定的属性存在于当前对象实例中(而不在实例的原型中)
function Person(name){
this.name=name
}
Person.prototype.setName=function(name){
this.name=name;
}
var person=new Person("aaaa");
console.log(person.hasOwnProperty("name"));//true
console.log(person.hasOwnProperty("setName"));//false
14)数组的方法:
reverse()、sort()、join()
concat():
var arr=["aaaa","bb",2];
console.log(arr.concat(2,"cc"));//["aaaa", "bb", 2, 2, "cc"]
console.log(arr.concat([2,"cc"]));//["aaaa", "bb", 2, 2, "cc"]
console.log(arr.concat([2],["cc"]));//["aaaa", "bb", 2, 2, "cc"]
console.log(arr.concat(2,[2],["cc",[6,7,8,9]]));//["aaaa", "bb", 2, 2, 2, "cc", [6, 7, 8, 9]]
slice():
var arr=[1,2,3,4,5,6,7,8,9];
console.log(arr.length);//9
console.log(arr.slice(0,3));//[1, 2, 3]
console.log(arr.slice(4));//[5, 6, 7, 8, 9]
console.log(arr.slice(-3,-1));//[7, 8]
<==>console.log(arr.slice(6,8));
console.log(arr.slice(-1,-3));//[]
<==>console.log(arr.slice(8,6));
console.log(arr.slice(1,-3));//[2, 3, 4, 5, 6]
<==>console.log(arr.slice(1,6));
splice():
插入或删除数组的通用方法:始终返回一个数组,数组中包含从原始数组中删除的项(否则返回空数组)
var arr=[1,2,3,4,5,6,7,8,9];
console.log(arr.splice(0,3));删除操作//[1,2,3]
console.log(arr);//[4, 5, 6, 7, 8, 9]
console.log(arr.splice(2,0,"cc","bb"));//插入操作,返回空数组[]
console.log(arr);//[4, 5, "cc", "bb", 6, 7, 8, 9]
console.log(arr.splice(2,1,"dd","eee","fff"));//替换["cc"]
console.log(arr);//[4, 5, "dd", "eee", "fff", "bb", 6, 7, 8, 9]
push():返回数组的新长度
pop():返回删除的元素
栈方法:先进后出(数组的尾部操作)
unshift():返回数组的新长度
shift():返回删除的元素
队列方法:先进先出(数组的头部操作);
15)函数:
参数arguments对象:
var fn=function(x,y){
console.log(x+"----"+y);
}
fn(1,2,"aa");//1----2
fn(1,2);//1----2
fn(1);//1----undefined
var fn=function(x,y){
var y="aaa"
console.log(x+"----"+y);
}
fn(1,2);//1----aaa
var fn=function(x,y){
arguments[0]="aaa"
console.log(x+"----"+y);
}
fn(1,2);//aaa----2
注意下面demo:
var fn=function(x,y){
var x="bb";
arguments[0]="aaa"
console.log(x+"----"+y);
}
fn(1,2);//aaa----2
方法:
apply(),call():
1)var fn=function(x,y){
console.log(x+"**"+y);
}
var obj={
fun:fn
};
console.log(obj.fun(2,3));//2**3
2)fn.call(obj,1,2);//1**2
=>window.fn.call(obj,1,2);
把1,2参数传递给fn,并把fn作为obj对象的方法调用
obj.fun=f;
obj.fun(1,2);
delete obj.fun;
3)fn.apply(obj,[1,2]);
a)找出一个数字数组中最大数字
var arr=[1,3,6,2,5,9,0];
var biggest=Math.max.apply(null,arr);
var str=Array.prototype.slice.apply(arr,[1,3]);
console.log(biggest);//9
console.log(str);//[3, 6]
16)对象工具函数:
/*
获取属性名集合
@param {object}
@retrun {array}
*/
function getPropertyNames(o){
var arr=[];
for(name in o){
arr.push(name);
}
return arr;
}
/*
copy对象集合
@param {object}//源对象
@param {object}//目的对象
@return {object}//返回对象
*/
function copyProperties(obj,newobj){
var newobj=newobj||{};
for(name in obj){
newobj[name]=obj[name];
}
return newobj;
}
/*
模拟jquery中合成对象
@param {object}//源对象
@param {object}//目的对象
@return {object}//返回对象
*/
function extend(){
var target=arguments[0]||{},
i=1,
len=arguments.length,
options,
name,
src,
dest,
deep=false;
if(typeof target ==="boolean"){
deep=target;
i=2;
target=arguments[1]||{};
}
if(typeof target!=="object"&&typeof target!=="function"){
target={};
}
for(;i<len; i++){
console.log(i);
if((options=arguments[i])!=null){
for(name in options){
var src=target[name];
var dest=options[name];
if(src==dest){
continue;
}
//深度拷贝
if(deep&&dest&&(typeof dest==="object"||Object.prototype.toString.call(dest)==='[object Array]')){
var clone = src && (typeof src==="object"|| Object.prototype.toString.call(src)==='[object Array]') ? src : typeof dest==="object" ? {} : [];
target[name]=extend(deep,clone,dest);
}
//浅度拷贝
else if(dest !== undefined){
target[name]=dest;
}
}
}
}
return target;
}
//看一个demo:
var s={
"name":{
"11":"11"
},
"sex":"male",
"age":30
}
var d={
"name":{
"11":"22",
"22":"44"
},
"student":false,
}
var c={
"name":{
"11":"33",
"33":"555"
},
"my":"me"
}
console.log(extend(true,s,d,c));