JavaScript中面向对象编程

时间:2021-09-06 15:48:07

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}

内存中存储结构:
JavaScript中面向对象编程

当有多个对象时,通过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),存储结构是这样的
JavaScript中面向对象编程

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

摘自:(http://liujiacai.net/blog/2015/02/01/javascript-oop/)