Self的原型机制是靠运行时的语意
Java的类机制是靠编译时的类语法
对象
- 在JavaScript中,除了Undefined、Null、Boolean、Number、String这几个简单类型外,其他的都是对象
- 在JavaScript中,有一些预定义的对象,比如Objective、Function、Date、Number、String、Array等,说白了对象就是一系列键值对,键可以是任意 可变的字符串,包括空串,值可以是任何值
- 在JavaScript中没有类的概念(class-free),但是他有一个原型链(prototype linkage),JavaScript对象是通过这个链实现继承关系的
使用对象字面量来创建
//创建一个空对象
var empty_object = {};
//创建了一个有俩个属性的对象
var strong = {
'name' = 'lily',
'age' = 12
};
当然亦可以通过new Object()或Object.create()的方式来创建对象
var per = new Object();
var foo = Object.create({x:10;, y:20});
原型链
javascript中每个对象都隐式含有一个prototype属性,这是ES的记法,目前各大浏览器在实现JavaScript解释器时,采用的记法是proto,也就是说每个对象都隐式包含一个proto属性
var foo = {x:10,y:20}
内存中存储结构:
当有多个对象时,通过proto属性就能形成一条原型链
var a = {
x:10,
calculate:function(z){
return this.x + this.y + z;
}
}
var b = {
y:20,
__proto__:a
};
var c = {
y:30,
__proto__:a
};
b.calculate(30);//60
c.calculate(40);//80
在声明对象b、c时,指明了它们的原型为对象a(a的原型默认指向Object.prototype,Object.prototype这个对象的原型指向null),存储结构是这样的
proto和prototype
在JavaScript中每个对象都有proto属性,但是只有函数对象有prototype属性
- proto 表示该函数对象的原型
- prototype 表示使用new来执行该函数时,新创建的对象的原型
var d = new Date();
d.__proto__ === Date.prototype; //这里为true
Date.__proto__ === Object.__proto__ //这里为true
instanceof
用于检测constructorFunction.prototype 对象是否在obj 的原型链中
function Car (name,age){
this.name = name;
this.age = age;
}
var myCar = new Car('lily',12);
myCar instance Car; //true
myCar instance Object; //true
函数对象Function
函数在JavaScript中无非也是个对象,可以作为Value赋值给某个变量,唯一不同的是函数能够被执行
- 使用对象字面量方式创建的对象的proto 属性指向Object.prototype(Object.prototype的proto属性指向null)
- 使用函数字面量创建的对象的proto属性指向Function.prototype(Function.prototype对象的proto属性指向Object.prototype)
-
函数对象除了proto这个隐式属性外,还有俩个隐式的属性
- 函数的上下文
-
实现函数的代码
//function关键字 //函数名省略了 //圆括号里的为参数 //花括号里的函数的执行语句 var add = function (a,b){ return a+b; }
函数调用与this
函数在被调用时,除了声明的参数外,还会有俩个额外的参数
- this
- arguments
this
this的值随着调用方式的不同而不同,JavaScript*有四种方式:
1、方法调用模式(method invocation patten)当函数作为某一个属性调用时,this指向这个对象,this赋值过程发生在函数调用时(也就是运行时)(late binding)
2、函数调用模式(function invocation patten)当函数不作为属性调用时,this指向全局对象
var add = function(a,b){return a + b};
var obj = {
value:3,
double:function(){
var self = this;//this赋值给self
this.value = add(self.value,self.value);
}
}
obj.double(); //6
3、构造调用模式(construct invocation patterm),javascript是一门原型继承语言,就说明对象可以直接从其他对象中继承属性,没有类的概念。当一个函数用new来调用时,this指向新创建的对象,这时的函数通常称为构造函数
4、apply调用模式(apply invocation pattern)使用函数对象的apply方法来执行时,this指向apply的第一个参数
//定义一个人类
function Person(name,age) {
this.name=name;
this.age=age;
}
//定义一个学生类
functionStudent(name,age,grade)
{
Person.apply(this,arguments);
this.grade=grade;
}
//创建一个学生类
var student=new Student("zhangsan",21,"一年级");
alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);
//测试结果:name:zhangsan age:21 grade:一年级
分析:
Person.apply(this,arguments);
this:在创建对象在这个时候代表的是student
arguments:是一个数组,也就是[“zhangsan”,”21”,”一年级”];也就是通俗一点讲就是:用student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面
arguments
函数在调用是额外传入的另一个参数是arguments。它是函数内部的一个变量,包含函数调用处的所有参数,甚至包含函数定义时没有的参数
var sum = function(){
var i, sum = 0;
//这里的arguments不是一个数组,它只是一个有length属性的类数组对象(Array-like),它并不拥有数组的其他方法。
for (i = 0;i<arguments.length;i+=1){
sum += arguments[i];
}
return sum;
}
sum(4,8,15,16,23,42)
结果:108