1. 函数传参数
Js : 只有按值传递。注意对象。
2. 没有块级作用域
Js : 没有块级作用域
3. Js 的数组长度属性是可读写的
4. 函数声明与函数表达式
Js:函数声明有个函数提升的过程,就变为全局可见。
function sum(a,b)
{
return a+b;
}
var sum = function(a,b){ return a+b; }; //要像声明其他变量一样,加分号结尾。
var sum = new Function("num1,","num2","return num1+num2");
// 会导致解析两次代码,一次解析常规ECMAScript,第二次解析传入构造函数的字符串。
5. Js的函数作为参数或者返回函数
function createComparisonFunction(protoName)
{
return function(obj1,obj2)
{
var value1=obj1[protoName];
var value2=obj2[protoName];
if(value1<value2){ return -1; }
else if(value1>value2){ return 1; }else{ return 0; }
};
}
6. Js 函数内部属性和方法
在函数内部有两个特殊对象:arguments 和 this
1. arguments.callee : 指向拥有这个arguments对象的函数。
function factorial(num)
{
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
2. this : 引用的是函数据以执行的环境对象。
caller : 指向调用当前函数的函数的引用。
function outer()
{
inner();
}
function inner()
{
alert(inner.caller);
//alert(argument.callee.caller);
}
outer(); // 输出outer的源代码
3.length 属性:表示函数希望接受的命名参数的个数
4. prototype : 对ECMAScript 的引用类型而言,prototype是保存它们所有实例方法的真正所在。
都保存在prototype名下,只不过通过各自对象的实例
访问罢了。在ESMAScript5中,prototype属性是
不可枚举的,因此使用for-in无法发现。
每个函数都包含两个非继承而来的方法:apply() 和 class(),在特定的作用域中调用函数。
接收两个参数,一个是作用域,一个是参数数组,
也可以是arguments对象。
5. apply() 方法
function sum(a,b)
{
return a+b;
}
function calssSum1(a,b)
{
return sum.apply(this,arguments);//传arguments对象
}
function calssSum1(a,b)
{
return sum.apply(this,[a,b]);//传数组
}
6. call() 方法
function calssSum1(a,b)
{
return sum.class(this,a,b);//给call的参数必须逐个列举出来。
}
真正的作用是扩充函数赖以运行的作用域:
window.color = "red";
var o = { color:"blue" };
function sayColor(){
alert(this.color);
}
sayColor();//red
sayColor().call(this);//red
sayColor().call(window);//red
sayColor().call(o);//blue
7. bind() 方法 : 绑定作用域
window.color = "red";
var o = { color:"blue" };
function sayColor(){
alert(this.color);
}
var objSayColor = sayColor.bind(o);
objSayColor(); // blue
7. Js 的基本包装类型
基本包装类型不是对象,因而逻辑上它们不应该有方法(但实际上有)。机制是:
(1)创建 String 类型对象
(2)在实例上调用指定的方法
(3)销毁这个实例
var s1 = "some text";
var s2 = s1.substring(2);
第二句在后台发生的情况:
var s1 = new Stirng("some text");
var s2 = s1.substring(2);
s1 = null;
引用类型和基本包装类型的主要区别是对象的生存期。
对象都为true。
var falseObject = new Boolean(false);
var result = falseObject && true;
alert(result); //true
var falseObject = false;
var result = falseObject && true;
alert(result); //false
typeof 引用类型返回"object"
8. Js 执行环境 和 作用域
执行环境都有一个与之相关联的变量对象。全局执行环境是最外围的一个执行环境。
每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。
而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
当代码在一个环境中执行时,会创建变量对象的一个作用域链。
作用域链的作用是保证对执行环境有权访问的
所有变量和函数的有序访问。作用域链的前端,始终是
当前执行环境的代码所在的变量对象。函数最开始只有arguments对象。下一个变量环境来自包含(外部)
环境。全局执行环境的变量对象始终是作用域链中最后
一个对象。
延长作用域链:
with:添加指定对象到作用域链中。
try-catch语句的catch块:创建新的变量对象。
9. 检测数组
if(value instanceof Array){
//...
}
instanceof 的问题在于,它假定单一的全局执行环境。如果网页中包含多个框架,
就存在两个以上不同的全局执行环境,
从而存在两个不同版本的Array构造函数。
解决办法: if(Array.isArray(value)){
//...
}
数组的迭代方法:
every();
fliter();
some();
map();
forEach();
10.对象
10.1 属性
1. 数据属性 :configurable,enumerable,writable,value
2. 访问器属性:configurable enumerable,set,get
单个属性:
Object.defineProperty(对象,属性,{值});
多个属性:
Object.defineProperties(book,{
_year:{
value:2004
},
edtion:{
value:1
},
year:{
get:function(){
return this._year;
},
set:function(newValue){
if(newValue>2004){
this._year=newValue;
this.edition+=newValue-2004;
}
}
}
});
11.构造方法
各个方法的缺点:
1.工厂方法: 不能确定是哪个对象。
2.构造函数方法:方法不是共享的,单独一份
3.原型方法:如果使用字面量声明,则constructor不指向实例,而是指向Object。全部共享
Box.prototype = {
constructor:Box //强制指向
}
原型的声明有先后顺序。单独可以修改,整体则被重写。
引用共享问题:构造函数 + 原型模式 解决
如果对原型中的引用类型进行修改,导致整个共享的原型被修改。
共享的使用原型,不共享的使用构造函数。
4.动态原型模式
把构造函数模式 ,与原型模式封装在一起。
原型模式,不管你是否调用原型模式中的方法,它都会初始化原型中的方法。
注意:使用这种模式不可以再使用字面量的方式重写原型,会切断实例与新源型之间的联系。
5.寄生构造函数
工厂模式 + 构造函数模式
6.稳妥构造模式
12.继承
用原型链继承。
function Box()
{
this.name = "Lee";
}
function Desk()
{
this.age = 100;
}
Desk.prototype = new Box(); //Desk 继承 Box
注意:
重写原型会断开实例与原型的联系。
添加原型不会。
13. 闭包
闭包只能取得包含函数中任何变量的最后一个值!
14. 匿名函数
匿名函数的执行环境具有全局性,所以只会搜索到this,arguments。只要把外部作用域中的this
保存到一个闭包可以访问的变量里,就可以了。