javaScript 的对象创建

  最近开始接触js,语法什么的都还行,唯独对于面向对象这一块的概念一直比较模糊,晚上的资料也都对照的看了看,总结了一下自己的理解。

  在传统的面向对象的语言如java中,都会有一个class类,class不是对象,它可以理解为是一张图纸。根据这些图纸创建的实例才是可以调用的对象。比方说我们有个锤子图纸,它有锤人的功能。我们只有把这个锤子按照图纸造出来,才能拿来锤人,要不然你拿个图纸去锤人,会被反杀的。

  但是在js的世界里面,没有图纸的概念,一切都是对象。可以理解为js对象就是一堆属性和方法的集合。下面就是一个简单的对象。

var Student = {
     name:'zhangsan',
     age:13,
     say:function(){
         console.log('my name is '+this.name + ', I am'+this.age+'years old!');
     }
    
}

  但是这种方法比较麻烦,如果每次创建对象我们都要用这种方式来构建,那就很坑爹了。你可以封装一个函数,传入name和age,函数来帮你构建,如下

function Student(name,age){
     return {
     name:name,
     age:age,
     say:function(){
         console.log('my name is '+this.name + ', I am'+this.age+'years old!');
         }
    }    
}

  这种方式也可以,但是这个对象每次都会开辟新的内存空间,比较不环保。上面两个方式完全没有面向对象编程的感觉,感觉还是面向函数式编程的样子,我们下面来了解下另外一种创建对象的方法《构造函数模式》。

  先看一个简单的栗子

function Student(name,age){
this.name = name;
this.age = age;
this.say = function(){
  console.log('my name is '+this.name + ', I am'+this.age+'years old!');
} }

var zhangsan = new Student('zhangsan',13);

zhangsan.say();

  到这一步已经有点面向对象的意思了,但是依旧没有解决上面栗子中的内存开销问题。这个时候我们需要了解js中另外一个东西,同时结构一下,new 函数的整个过程。

   JavaScript中没有类的概念,但是JavaScript中有一个原型的概念prototype。当已存在一个对象的时候,可以通过指定对象的prototype的方法来,来依据已存在的对象创建新的对象。有点绕,直接上代码。

var Student = {
     name:'zhangsan',
     age:13,
     say:function(){
         console.log('my name is '+this.name + ', I am'+this.age+'years old!');
     }
}

var Student2 = {name:'lisi'}
Student2.__proto__=Student
Student2.say()

  上面代码中,我们首先有了Student对象,再创建Student2对象,同时指定Student2对象的__proto__属性继承Student对象的age 和 say属性,name其实也继承了只是被重写了。

  这就是javaScript中的原型的概念,其实说白了就是当我们调用对象的属性和方法的时候,首先会调用自己的属性方法,当没有找到的时候就会到__proto__中去找有没有相关的属性和方法。

  每个对象都有自己的原型链,比如我们定义了一个数组类型arr = [],那么它的原型链就是arr ---->Array.prototype---->Object.prototype---->null。

  其实基本上和java的继承类似,那么我们再返回上面的构造函数模式中,创建对象的全过程,我们先看看伪代码

var obj = {}
obj.__proto__ = Student.prototype
Student.apply(obj, arguments)
return obj

  第一行代码是创建一个空对象。

  第二行是将空对象的原型属性指向构造函数Student的prototype属性,在这里要声明一下,在javaScript的规定里面,每个构造函数都有一个prototype属性。

  第三行的代码就是将构造函数的作用域赋予给对新对象,将构造函数中的this指向新对象。

  第四行返回对象

  通过上面的过程我们大致理解了构造函数创建过程,这个时候我们再思考一下前面的问题,关于对象创建时,重复创建函数的问题。我们可以对构造函数的prototype属性进行赋值,使所有的对象都指向同一个构造函数的prototype属性,这样我们就可以解决之前内存不环保的问题,这就表示我们可以把一些不变的方法或者属性定义在prototype属性上,下面我们上代码

function Student(name,age){
this.name = name;
this.age = age;
}

Student.prototype.say = function(){
  console.log('my name is '+this.name + ', I am'+this.age+'years old!');
} 
student = new Student()
student.say()

 

其实本质上来讲,javascript面向对象的思想和别的语言差不多,只是因为没有使用class所以理解上有点别扭,但是从es6开始,javascript开始支持class关键字,我们可以像使用java一样来创建class,再根据class来new出对象来。但是为啥现在没有流行起来,我看到一些资料是说有些浏览器不支持es6,很多主流项目也没有引入class,如果要改的话,重构的工作应该也比较大。

 

posted @ 2017-10-18 17:07  soultank  阅读(104)  评论(0编辑  收藏  举报