js-变量、作用域和内存问题,引用类型
变量、作用域和内存问题
1、变量可能包含两种不同数据类型的值;基本类型值以及引用类型值;引用类型值保存的是内存中的对象
2、对象是按值传递的,
function setName(obj){
obj.name="zhang";
obj=new Object();
obj.name="hui";
}
var person=new Object();
setName(person);
alert(person.name); //zhang
//在函数中将person对象作为参数传给setName,
在函数中又创建了一个新的对象,并且重新对name赋值,
但在外部访问person.name的时候,结果还是zhang,因为函内部重写obj
的时候,这个变量引用就是一个局部变量,在函数执行介绍后就被立即销毁
3、如果变量值是一个一个对象或者null,typeOf操作符会返回一个object。
如果变量是给定引用类型的实例,instanceof操作符会返回true:
result=variable instanceof constructor -----检测对象
eg:alert(person instanceof Object);//变量person是Object吗?
alert(colors instanceof Array);//变量colors是Array吗?
在检测一个引用类型值和Object构造函数时,instanceof会始终返回true,检测基本数据类型的时候会返回false;
4、执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。执行环境中所有代码执行完毕后,环境被销毁,保存在其中的所有变量以及函数定义也会随之销毁,全局执行环境要直到应用程序退出才销毁,例如关闭网页或浏览器
5、内部环境可以通过作用域链访问所有外部环境,外部环境不能访问内部环境中的任何变量以及函数。任何环境都不能通过向下搜索作用域链而进入另一个执行环境。
6、初始化变量时,没有添加var声明,该变量会自动添加到全局环境中
7、如果在函数的局部变量中有一个同名的变量,会使用局部变量而不会再向上查找
8、在IE以及Opera7以上的版本中,window.CollectGarbage()方法会立即执行垃圾收集
9、基本数据类型在内存中占据固定大小的空间,因此被保存在栈内存中
引用类型的值是对象,保存在堆内存中
引用类型:
1、
第一种方式:
var person=new Object();
person.name="zhang";
person.age=29;
第二种方式:
var person{
name:"zhang",
age:29
};
//在age之后不能有逗号,因为age是最后一个属性
第三种方式:
var person{
"name" : "zhang",
"age" : 29,
5 : true
};
//这里的数值属性会自动转化为字符串
第四种方式:
var person={}; -----与new Object()相同
person.name="zhang";
person.age=29;
2、访问对象属性:
alert(person[“name”]);
alert(person.name);
//方括号语法的优点是可以通过变量来访问属性
eg:var propertyName="name";
alert(person[propertyNmae]);
如果属性名中包含会导致语法错误的字符,或者属性名中使用的是关键字或保留字,
也可以使用方括号表示法
eg:person["first name"]="zhang";
//first name中包含一个空格,不能使用点表示法,属性名中包含非字母非数字的,
可以使用方括号表示法对它进行表示
3、Array类型
A: var colors=new Array();
var colors=new Array(20); ----length为20
var names=new Array("Greg");
var colors=["red","blue","green"];
var names=[];----创建一个空数组
B:length属性不是只读的,长度为3,将长度属性值设为2的时候,会移除最后一项,当再访问第三项的时候就会显示undefined
使用length在数组末尾添加,
Eg:var colors=["red","blue","green"];
colors[colors.length]=“black”;-----在位置3添加一个颜色
colors[colors.length]=“red”;-----在位置4添加一个颜色
C:检测某值是不是数组
If(Array.isArray(value)){}
D:所有对象都有toLocaleString()、toString()、valueOf()方法,其中toString()方法会返回由数组中每个值的字符串拼接而成的以逗号分隔的字符串;valueOf()返回的还是一个数组。
var colors=["red","blue","green"];
alert(colors.toString()); //red,blue,green
alert(colors.valueOf()); //red,blue,green
alert(colors);//red,blue,green
E: var person1={
toLocaleString : function(){
return "zhang";
},
toString : function(){
return "zhang";
}
};
var person2={
toLocaleString : function(){
return "hui";
},
toString : function(){
return "yun";
}
};
var people=[person1,person2];
alert(people); //zhang,yun
alert(people.toStrinr()); //zhang,yun
alert(people。toLocalleString()); //zhang,hui
//将数组传递给alert的时候,调用了数组的toString方法
F:使用join()方法作为字符串的分隔符:alert(colors.join(”、、”));
G:栈方法:(移除返回项,添加返回长度)
push():添加到数组的末尾,返回修改后数组的长度
pop():从数组末尾移除最后一项,减少数组的length,然后返回移除的项
colors[3]=“black“;----直接添加
H:对列方法:(移除返回项,添加返回长度)
shift()移除数组中的第一项并返回该项,同时将数组长度减1
unshift()方法再数组的前端添加任意多个项并返回新数组的长度
I:重排序方法:reverse()、sort()
reverse()会反转数组项的顺序
sort()默认情况下按升序排列数组项,会调用每个数组项的toString()转型方法,然后比较得到的字符串
J:创建新数组:concat()方法
var colors=colors.concat(”yellow”,[“black” , “brown”]);
基于当前数组中的一或多项创建一个新数组:slice()方法—可以接受一个或两个参数,即返回项的指定位置到指定结束位置(不包括结束位置的项)
var colors=["red","green","blue"];
var colors1=colors.slice(1); --green,blue
var colors2=colors.slice(0,2); ----red,green
splice()方法:向数组的中部插入项,返回的是数组
splice(0,2)---要删除的第一项的位置,删除的项数
splice(2,0,”red”,”green”)—起始位置,要删除的项数,要插入的项-----从位置2开始插入
splice(2,1,”red”,”green”)—先删除再添加
K:indexOf()以及lastIndexOf()方法,包含两个参数,一个是要查找的项,还有一个是查找起点位置的索引
indexOf()---从0开始查找
lastIndexOf()----从数组的末尾开始查找
在没找到的情况下返回-1
L:迭代方法:
1) every():对数组中的每一项运行给定函数,如果该函数是对每一项都返回true,则返回true
2) filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
var numbers=[1,2,3,4,5,4,3,2,1]
var filterResult=numbers.filter(function(item,index,array){
return (item>2);
});
alert(filterResult); //[3,4,5,4,3]
3) forEach():对数组中的每一项运行给定函数,没有返回值
4) map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
var numbers=[1,2,3,4,5,4,3,2,1]
var mapResult=numbers.map(function(item,index,array){
return item;
});
alert(mapResult);
5) some():对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true
M:归并方法:reduce()以及reduceRight(),两个方法都会迭代数组的所有项,并且构建一个最终返回的值,接收两个参数,在每一项上调用的函数以及(可选的)作为归并基础的初始值;
函数接收4个值,前一个值,当前值,项的索引,数组对象
reduce()是从数组的第一项开始,逐个遍历
reduceRight()是从数组的最后一项开始,向前遍历到第一项
4、Date类型
A:第一种方法:
//取得开始时间
var start=Date.now();
doSomeThing();
//取得结束时间
var stop=Date.now(),
result=stop -start;
第二种方法:
//取得开始时间
var start=+new Date();
doSomeThing();
//取得结束时间
var stop=+new Date(),
result=stop -start;
5、RegExp类型
var expression =/ pattern / flags ;
//每个正则表达式都可带有一个或多个标志,标明正则表达式的行为
flags可以是g(全局);i(不区分大小写);m(多行模式,到达一行文本末尾时)
6、Function类型
A:
function sum(num1,num2){
return num1+num2;
}
alert(sum(10,10));
var anotherSum=sum;
alert(anotherSum(10,10));
//sum与anotherSum都是指向同一函数,所以anotherSum()可以被调用
sum=null;
alert(anotherSum(10,10));
//将sum设为null,让他与函数“断绝关系”,但anotherSum()还是可以正常调用
B:不仅可以像传参一样将一个函数传递给另一个函数,还可以将一个函数作为另一个函数的结果返回
function getGreeting(name){
return "hello," + name;
}
var result=callSomeFunction(getGreeting,"zhang");
alert(result); ------"hello, zhang"
C:访问函数的指针而不执行函数,使用不带圆括号的函数名是访问函数的指针,而非调用函数
D:函数内部属性,两个特殊对象:arguments,this。Arguments是保存函数参数,该对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数,eg:阶乘
function factorial(num){
if (num<=1) {
return 1;
}else{
//return num*factorial(num-1)
return num*arguments.callee(num-1)
}
}
E:函数对象属性caller:保存着调用当前函数的函数的引用,如果在全局作用域中调用当前函数,它的值为null
F:函数的方法:
apply():在特定作用域中调用函数,第一个参数是在其中运行函数的作用域,第二个是参数数组,其中,第二个可以是Array的实例,也可以是arguments对象
function sum(num1,num2){
return num1+num2;
}
function callSum1(num1,num2){
return sum.apply(this,arguments);
}
function callSum2(num1,num2){
return sum.apply(this,[num1,num2]);
}
alert(callSum1(10,10)); ---20
alert(callSum2(10,10)); ---20
call():在特定作用域中调用函数,第一参数是this,第二个参数中,传递给函数的参数必须逐个列举出来
function sum(num1,num2){
return num1+num2;
}
function callSum1(num1,num2){
return sum.call(this,num1,num2);
}
alert(callSum1(10,10)); ---20
F:object构造函数,根据传入值的类型返回相应基本包装类型的实例
var obj=new Object("some text");
alert(obj instanceof String); //true
将字符串传给Object构造函数,创建String实例
G:Boolean类型:布尔表达式中的所有对象都会被转为true,不建议使用布尔对象
H:Number类型
1) var num=10;
alert(num.toFixed(2)); //“10.00”
//toFixed(2)表示要显示几位小数,如果数值本身包含的小数位比指定的多,会舍入---将数值格式化为字符串
2) toExponential ()方法,返回以指数表示法(e表示法),接收一个参数,表示输出结果中的小数位数---将数值格式化为字符串
var num=10;
alert(num.toExponential(1)); //"1.0e+1"
3) toPrecision()方法会返回一个最适合的格式
I:String类型:
1) charAt()方法以单字符串的形式返回给定位置的那个字符
var stringValue="hello world";
alert(stringValue.charAt(1)); //"e"
2) charCodeAt()得到字符编码
var stringValue="hello world";
alert(stringValue.charCodeAt(1)); //"101"
3) var stringValue="hello world";
alert(stringValue[1]); //"e"
4) concat()将一或多个字符串拼接起来,返回拼接得到的新字符串
var stringValue="hello world";
alert(stringValue.slice(3)); //"lo world"
alert(stringValue.substring(3)); //"lo world"
alert(stringValue.substr(3)); //"lo world"
alert(stringValue.slice(3,7)); //"lo w" 第二个参数指定的是子字符串最后一个字符后面的位置,就是说不包括7
alert(stringValue.substring(3,7)); //"lo w" 第二个参数指定的是子字符串最后一个字符后面的位置,就是说不包括7
alert(stringValue.substr(3,7)); //"lo worl" 第二个参数表示返回的字符个数
当传入的值是负值的时候:
var stringValue="hello world";
alert(stringValue.slice(-3)); //"rld" 实际参数=字符串的长度+参数
alert(stringValue.substring(-3)); //"hello world" 将负数参数转为0
alert(stringValue.substr(-3)); //"rld" 将负的第一个参数加上字符串长度,将负的第二个参数转为0
alert(stringValue.slice(3,-4)); //"lo w"
alert(stringValue.substring(3,-4)); //"hel" 将-4转为0,(3,0),较小的作为开始位置,大的作为结束位置
alert(stringValue.substr(3,-4)); //""
5) 从字符串中查找子字符串的方法:indexOf()以及lastIndexOf()方法,返回子字符串的位置,没有找到则返回-1
indexOf()从开头开始查找,lastIndexOf()由末端向前搜索
6) 删除前置以及后缀的空格,返回结果:trim()
7) 字符的大小写转换方法:toLowerCase()以及toUpperCase()
8) replace():
var text="cat,bat,sat,fat";
var result=text.replace("at","ond");
alert(result); //"cond ,bat , sat , fat"
var result=text.replace("/at/g","ond");
alert(result); //"cond , bond, sond, fond"
9) split()基于指定的分隔符将一个字符串分割为多个子字符串,并将结果放在一个数组中
7、禁止给undefined、NaN、indefinity赋值
8、Math对象:
1) min(),max()方法,可以接收任意个数值参数
var max=Math.max(2,3,4,5);
alert(max);
***********
var values=[2,3,5,6,7,8];
var max=Math.max.apply(Math,values)
2) 舍入方法:
Math.ceil()执行向上舍入
Math.floor()执行向下舍入
Math.round()执行四舍五入
3) Math.random()返回一个大于等于0小于1的随机数