1. JavaScript对象
JavaScript是面向对象的,但并没有类的概念,后续版本增加的,但实际上还是依赖原型来实现的(语法糖)。
面向对象的三大特征:封装、继承、多态。多态的体现就是继承,
js的基石–ECMAScript中对象(Obeject)的定义:
Object是一个属性的集合,并且都拥有一个单独的原型对象[prototype object]. 这个原型对象[prototype object]可以是一个object或者null值。
一个Object的prototype是一个内部的[[prototype]]属性的引用。
一般来说,会使用__<内部属性名>__ 下划线来代替双括号,例如__proto__。
2. 原型链
原型链是一个由对象组成的有限对象链用于实现继承和共享属性。
原型对象也和普通对象一样,可以拥有自己的原型对象,如果它的原型对象不为空,就形成了原型链(prototype chain)。在引用对象实例的某一属性时,会先在对象的属性中寻找,找不到会到对象的原型中寻找,直到原型链的顶端Object.prototype还没有找到就返回undefined。
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调用方法时,方法中的this指向的仍然是当前的对象(b或c),而对于在自身对象中没有找到的属性则是调用通过原型链找到的对象的属性(比如使用a的x属性)。
this是没有一个类似搜寻变量的过程。当你在代码中使用了this,这个 this的值就直接从执行的上下文中获取了,而不会从作用域链中搜寻。this的值只取决中进入上下文时的情况。
3. 构造函数
js中的构造函数为创建的对象设置了原型对象,构造函数中的prototype属性指向的就是该原型函数。而构造函数自己的__prototype__属性指向的是Function.prototype这一对象,Function.prototype对象的__prototype__属性指向的是Object.prototype。
// 构造函数
function Foo(y) {
// 被创建的对象都会有"y"属性
this.y = y;
}
//用于 继承属性"x"
Foo.prototype.x = 10;
//用于 继承方法"calculate"
Foo.prototype.calculate = function (z) {
return this.x + this.y + z;
};
// 构造函数创建对象
var b = new Foo(20);
var c = new Foo(30);
// 调用继承的方法
b.calculate(30); // 60
c.calculate(40); // 80
有趣的是构造函数的prototype指向的原型对象持有的constructor属性指向的该构造函数,这样,属性x也得以被使用该构造函数创建的对象所继承,循环引用,我自己引用我自己哈哈哈。
- js中的new运算符:区别于其它面向对象语言中new的含义,它只是调用一个构造函数。ECMA 完全可以用其它 非new 表达式来用调用构造器创建对象,只是为了贴近java。
- instanceof运算符:判断是否为构造函数的实例,typeof运算符则返回对象的类型,如number,boolean,string,function(函数),object(NULL,数组,对象),undefined。