您的位置:首页 > Web前端 > JavaScript

2. Js 细节

2015-08-28 11:20 676 查看
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
保存到一个闭包可以访问的变量里,就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: