ECMAscript5
一、预处理阶段
全局环境(就是window对象)
记录所在作用域代码中声明的变量
记录所在作用域代码中声明的函数
函数环境
同全局词法环境相同相同(记录所在作用域代码中声明的变量
记录所在作用域代码中声明的函数)
记录参数并赋值变量提升
alert(num);
var num=10;
输出:undefined,因为变量提升,代码预处理阶段是这样的
num=undefined;
alert(num);
var num=10;
以下代码运行结果是什么?
<script>
var num = 10;
function fun(){
alert(num);
var num = 100;} //局部变量
fun()
</script>
预处理阶段:
window{
num:undefinde;
fun:‘{alert(num);var num = 100;}’ }
函数环境{
num:undefined }
输出:Undefined()
二、变量的类型
值类型
Number Boolean String Null undefined
引用类型
Array Object。。。
变量的内存保存方式
//值变量保存在内存的栈区,变量之间复制数据,互不相干
var name = 'tom';
var name1 = name;
name1 = 'jack';
alert(name); //输出tom
//对象保存在内存的堆区,引用变量共同指向同一个对象,共享数据
var p = new Object();
p.name = 'tom';
var p1 = p;
p1.name = 'jack';
alert(p.name); //输出jack
二、作用域类型
全局作用域
函数作用域
三、作用域链
函数嵌套形成作用域的层级关系函数执行时,从当前作用域开始搜寻变量,如果没有 往上一级搜寻,一直到全局作用域为止
四、闭包
闭包是引用外部自由变量的函数
function f1(){
var a = 10;
var b = 20;
function f2(){
console.log(a);} //必须使用外部变量,形成闭包
f2();}
f1()
1、特点
闭包的函数和自由变量一同存在,即使离开了创建环境
闭包的本质是作用域链
function f1(){
var a = 10;
var b = 20;
return function f2(){
console.log(a);
}
}
var result = f1();
result();
闭包的应用
减少全局变量的定义
封装对象的成员
闭包的缺点
内存无法释放
逻辑错误
五、对象
js中构造函数名大写开头
Javascript中可以采用简便的字面量方式创建对象
var obj = {
stuName:‘Tom’,
stuSex:‘男’,
stuAge:20,
sayHello:function(){
alert(“你好!”);
}
}
创建对象简便快捷,属性和值映射关系清晰
主要适用于一个实例对象的场合,缺乏封装性和重用
Object方式创建对象
var person = new Object(); //创建对象
person.name = name
person.age = age;
person.sayHi = function(){
alert(‘你好!我是’ + this.name);
}
封装Object方式创建对象
function createObject(name,age){
var person = new Object(); //创建对象
person.name = name
person.age = age;
person.sayHi = function(){
alert(‘你好!我是’ + this.name);
}
return person;
}
封装Object创建对象的方式也称为工厂模式
对象的属性可以动态添加,结束时需要返回
对象存在的不足是无法辨别对象的具体类型
构造函数方式
function Human(name,age){
this.name=name;
this.age=age;
this.show = function(){
alert(‘你好!我是’ + this.name);
}
}
构造方法在创建对象时发挥作用,不创建对象时和普通方法相同
构造方法名首字母大写,通过new关键字创建实例对象
var peo=new Human("hu",23);
构造方法中不需要创建对象,也不用返回,依靠this关键字实现属性的设置
构造方法的对象是独立存储的,缺少共享,内存空间消耗较大
原型方式
function Human(){}
Human.prototype.name =“tom”;
Human.prototype.age = 22;
Human.prototype.show = function(){
alert(‘你好!我是’ + this.name);
}
原型方式实现对对象成员的共享,节省存储空间
引用导致实例对象的相互影响
混合方式
function Human(name,age){ this.name=name; this.age=age;
}
Human.prototype.country =“CHN”;
Human.prototype.show = function(){
alert(‘你好!我是’ + this.name);
}
混合方式结合了构造函数方式和原型方式
构造函数方式用于定义实例的属性,而原型方式用于定义方法和共享的属性
支持向构造函数传递参数
六、继承
1、类继承
通过call、apply方法实现类的继承
function Human(name,age){
this.hand = 2;
this.head = 1;
this.name = name;
this.age = age;
this.show = function(){
alert('我是' + this.name)
}
}
function Student(name,age){
//Human.call(this,name,age); //call方式实现继承
Human.apply(this,[name,age]); //apply方式实现继承
}
var student = new Student('tom',20);
student.show();
2、原型组合继承
通过原型和构造函数实现继承
<script>
function Father(name){
this.name=name;
this.color=["red","yellow"]
}
Father.prototype.sayName=function () {
alert(this.name)
};
function Son(name,age) {
Father.call(this,name); //构造函数继承
this.age=age;
}
Son.prototype=new Father(); //原型继承,原型对象等于另一个类型的实例
Son.prototype.sayAge=function () {
alert(this.age)
};
var demo1=new Son('hu',20);
demo1.color.push("black"); //输出red,yellow,black
alert(demo1.color);
demo1.sayName(); //输出hu
demo1.sayAge(); //输出 20
</script>
七、面向对象
对象是属性的集合
函数和对象的关系
对象都是通过函数生成的(new)
函数也是一种对象
函数的prototype属性指向原型对象,原型对象中的constructor指向函数
对象具有隐性属性proto,指向原型对象
//对象和函数的关系
//通过new+构造函数创建实例对象
var obj1 = new Object();
var obj2 = new Object();
//不同的实例对象通过__proto__访问相同的原型对象
alert(obj1.__proto__ === obj2.__proto__);
//通过构造函数的proto也可以访问原型对象
alert(obj1.__proto__ === Object.prototype);
//原型对象中具有一个constructor属性,该属性指向构造函数
console.log(Object.prototype);