JavaScript 笔记

1浏览器一般会按照<script>元素在页面中出现的先后顺序对它们依次进行解析。

2设置了defer="defer"属性的<script>表明脚本在执行时不会影响页面的构造。也就是说,脚本会被延迟但整个页面解析完毕后再运行。HTML5规范要求脚本按照它们出现的先后顺序执行,而且要先于DOMContentLoaded事件执行。(但在现实中并不能保证这两点。因此最好只包含一个延迟脚本)

3设置了ansyc属性的<script>脚本与defer类型,但不保证按照多个文件按照出现的先后顺序执行,因此要确保多个文件之间互不依赖,建议异步脚本不要在加载期间修改DOM。异步脚本一定会在load事件前执行,但可能会在DOMContentLoaded事件触发之前或之后。(Firefox 3.6, Safari 5, chrome支持ansyc)

1. var 的作用

Var JavaScript中是声明变量的作用,当然因为JavaScript是松散语言,所有也可以不使用var声明变量。

// These are both globals
var foo = 1;
bar = 2;
 
function test()
{
    var foo = 1;// Local
    bar = 2;    // Global
 
    // Execute an anonymous function
    (function()
    {
        var wibble = 1;// Local
        foo = 2;// Inherits from scope above (creating a closure)
        moo = 3;// Global
    }())
}

上面这个示例告诉我们,如果你不用var,那么这个js引擎会一层一层地向上找父作用域中的变量,如果找到了,就用,如果找不到了,就会帮你定义一个全局的变量。上面这个例子充分说明了这一点。所以,如果你想在当前的作用域用声明变量,你一定要用var

参考:http://coolshell.cn/articles/7480.html 


2. JS变量

2.1 局部变量先使用后声明,不影响外部同名变量。

var x = 1;// --> 外部变量x
fn();	//可以在声明前调用,不推荐
function fn(){
    alert(x); // --> undefined 局部变量x先使用
    var x = 2;// 后声明且赋值
    alert(x); // 2
}
alert(x);// --> 1

在函数 fn 中由于声明了变量x,所有会把全局变量x给覆盖掉。在第一个alert(x)中,因为并没有对局部变量x赋值,因此结果是 underfined。在第二个alert(x)中,显示的是局部变量x的值。在第三个alert(x)中显示的是全局变量x的值。

2.2 同名变量指向同一块内存

var str = "zzj";
function fn(a)
{
	var a;
	alert(a);	 //hello
	alert(arguments[0]);//hello
	var a = 1;
	alert(a);	 //1
	alert(arguments[0]);//1
}
fn("hello");
var str;
alert(str);	// zzj

在函数中可以通过形参名和arguments来访问传入的值,它们是指向同一块内存的,我们虽然声明了多个与形参同名的变量,但可以发现,同名变量时指向同一块内存。


3. JavaScript的词法作用域

函数在定义它们的作用域里运行,而不是在执行它们的作用域里运行。

调用对象位于作用域链的前端,局部变量(在函数内部用var声明的变量)、函数参数及Arguments对象都在函数内的作用域中——这意味着它们隐藏了作用域链更上层的任何同名的属性。

var i = 1;  
    function a() {  
        alert(i); // undefined  
var i = 2;  
        alert(i); // 2  
    }  
a();  

参考:http://www.cnblogs.com/mophee/archive/2009/03/15/1412590.html

            http://js8.in/745.html 


4. 闭包

闭包是定义在函数内部,并能够读取其他函数内部变量的函数。

JS里的function能访问它们的:

  1. 参数

  2. 局部变量或函数

  3. 外部变量(环境变量?),包括

3.1 全局变量,包括DOM

3.2 外部函数的变量或函数。

如果一个函数访问了它的外部变量,那么它就是一个闭包。

闭包的用途:

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

var db = (function() {
// 创建一个隐藏的object, 这个object持有一些数据
// 从外部是不能访问这个object的
var data = {};
// 创建一个函数, 这个函数提供一些访问data的数据的方法
return function(key, val) {
    if (val === undefined) { return data[key] } // get
    else { return data[key] = val } // set
    }
// 我们可以调用这个匿名方法
// 返回这个内部函数,它是一个闭包
})();
db('x'); // 返回 undefined
db('x', 1); // 设置data['x']为1
db('x'); // 返回 1
// 我们不可能访问data这个object本身
// 但是我们可以设置它的成员

使用闭包的注意点:

1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2、闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

参考:http://kb.cnblogs.com/page/110782/

   http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

5. 继承和原型链

5.1 对象冒充

function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function () {
        alert(this.color);
    };
}
function ClassB(sColor, sName) {
    this.newMethod = ClassA;
    this.newMethod(sColor);
    delete this.newMethod;

    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}
var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.sayColor();    //输出 "blue"
objB.sayColor();    //输出 "red"
objB.sayName();     //输出 "John"

对象冒充还可以实现多重继承

function ClassZ() {
    this.newMethod = ClassX;
    this.newMethod();
    delete this.newMethod;

    this.newMethod = ClassY;
    this.newMethod();
    delete this.newMethod;
}

在多重继承中如果存在两个类 ClassX 和 ClassY 具有同名的属性或方法,ClassY 具有高优先级。因为它从后面的类继承。除这点小问题之外,用对象冒充实现多重继承机制轻而易举。

Call() 方法

function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.call(this, sColor);

    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

Apple()方法

function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.apply(this, arguments);

    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

Call() 和 apple() 方法是的使用对象冒充方法继承代码更简洁。

5.2 原型链

prototype 对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。

function ClassA() {
}
ClassA.prototype.color = "blue";
ClassA.prototype.sayColor = function () {
    alert(this.color);
};
function ClassB() {
}
ClassB.prototype = new ClassA(); //确保构造函数没有任何参数
ClassB.prototype.name = "";
ClassB.prototype.sayName = function () {
    alert(this.name);
};

原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 prototype 属性。

5.3 混合方式

对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。

创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。

function ClassA(sColor) {
    this.color = sColor;
}
ClassA.prototype.sayColor = function () {
    alert(this.color);
};
function ClassB(sColor, sName) {
    ClassA.call(this, sColor);
    this.name = sName;
}
ClassB.prototype = new ClassA();
ClassB.prototype.sayName = function () {
    alert(this.name);
};
var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.sayColor();    //输出 "blue"
objB.sayColor();    //输出 "red"
objB.sayName(); //输出 "John"


参考:http://www.w3school.com.cn/js/pro_js_inheritance_implementing.asp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值