05 JS面向对象
来源:互联网 发布:mysql是大型数据库吗 编辑:程序博客网 时间:2024/04/30 13:44
声明对象
对象分两种,函数对象和普通对象,使用new Function()声明的都是函数对象,Object ,Function 是 JS 自带的函数对象,其它的都是普通对象。JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做proto 的内置属性,用于指向创建它的构造函数的原型对象。每个函数对象都有一个prototype属性,指向它的原型对象,普通对象只有一个proto属性。
使用字面量
下面代码使用字面量声明两个对象:Byron和Casper
var obj1 = { nick: 'Byron和', age: 20, printName: function(){ console.log(obj1.nick); }}var obj2 = { nick: 'Casper', age: 25, printName: function(){ console.log(obj2.nick); }}
这样构造有两个明显的问题:
1.太麻烦了,每次构建一个对象都是复制一遍代码
2.如果想个性化,只能通过手工赋值,使用者必需了解对象详细
这两个问题其实也是我们不能抛开类的重要原因,也是类的作用。
我们可以通过创建一个函数来实现自动创建对象的过程,至于个性化通过参数实现,开发者不必关注细节,只需要传入指定参数即可。
使用构造函数
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { alert(this.name) } }var p1 = new Person('Tom', 28, 'Software Engineer');var p2 = new Person('Jack', 23, 'Doctor');p1 instanceof Person; // truep1 instanceof Object;// trueconsole.log(p1.constructor == Person); //trueconsole.log(p2.constructor == Person); //true
在内存中的对应关系如图所示:
p1 和 p2 都是 构造函数 Person 的实例
1、使用构造函数创建出来的p1和p2,可以使用instanceof 来判断它们是否是Person的实例
2、实例的构造函数属性(constructor)指向构造函数。
构造函数方法很好用,但是存在一个浪费内存的问题,如图所示,实例都从构造复制了一份属性和方法在内存中,能不能有一个所有实例都可以访问到的一个公共容器,重复的东西移动到公共容器里放一份就可以了?答案是可以的,原型对象(prototype)就是解决这个问题的。原型对象,最重要的作用就是把常量和方法独立到自身里,供给其它 “自己的对象” 使用,下面详细讲解原型对象。
在实例化对象的时候使用了new关键字,new的过程拆分成以下三步:
(1) var p1={}; 也就是说,初始化一个对象p
(2) p1.[[proto]] = Person.prototype;
(3) Person.call(p1); 也就是说构造p,也可以称之为初始化p
原型对象
示例代码:
function Person(nick, age){ this.nick = nick; this.age = age;}Person.prototype.sayName = function(){ console.log(this.nick);}var p1 = new Person('Byron',20);var p2 = new Person('Casper',25);p1.sayName();//'Byron'p2.sayName();//'Casper'
这时候我们对应的关系是这样的:
如图所示:
p1和p2都具有了原型对象的sayName方法,它们都有一个[[proto]]属性,都指向Person的prototype(原型对象),无论Person有多少个实例,这样就实现了面向对象中的继承。
原型对象还有一个constructor属性,这个属性(是一个指针)指向 prototype 属性所在的函数(Person),关系如下代码:
p1.constructor == PersonPerson.prototype.constructor == Person
原型链
上文说过每个对象都有一个内置的[[proto]]属性,指向创建它的函数对象的原型对象prototype。
示例代码:
function Task(id){ this.id = id; } Task.prototype.status = "STOPPED"; Task.prototype.execute = function(args){ return "execute task_"+this.id+"["+this.status+"]:"+args; } var task1 = new Task(1); var task2 = new Task(2); task1.status = "ACTIVE"; task2.status = "STARTING"; print(task1.execute("task1")); print(task2.execute("task2"));
执行结果:
execute task_1[ACTIVE]:task1
execute task_2[STARTING]:task2
构造器会自动为task1,task2两个对象设置原型对象Task.prototype,这个对象被Task(在此最为构造器)的prototype属性引用,参看下图中的箭头指向。
由于Task本身仍旧是函数,因此其”[[proto]]”属性为Function.prototype, 而内建的函数原型对象的”[[proto]]”属性则为Object.prototype对象。最后Obejct.prototype的”[[proto]]”值为null。
结论:
1.原型和原型链是JS实现继承的一种模型。
2.原型链的形成是真正是靠[[proto]] 而非prototype
如下代码:
var animal = function(){};var dog = function(){};animal.price = 2000;//dog.prototype = animal;var tidy = new dog();console.log(dog.price) //undefinedconsole.log(tidy.price) // 2000
内存如图所示:
最后用一张图来总结JS原型与原型链:
- 05 JS面向对象
- js面向对象尝试
- js面向对象
- 面向对象的js
- js中的面向对象
- JS面向对象
- JS面向对象2
- 06 JS面向对象
- JS 面向对象
- JS面向对象例子
- 面向对象 js 打包
- js面向对象设计
- js面向对象
- js--面向对象
- js面向对象总结
- js面向对象工作总结
- js面向对象
- js面向对象
- Linux下查看SSD4K对齐EXT4分区开启Trim及验证的方法
- iOS 开发者必须知道的新特性
- 【七】最优间隔分类器问题
- 存储过程-第三课(函数)
- 【record】10.17..10.23
- 05 JS面向对象
- 公司研发人员(含测试)经理、组长能力评价表
- 海洋泡沫结点图完整分析
- leetcode 414. Third Maximum Number
- python-Django中设置操作shell时执行的数据库命令在控制台显示
- 【动态规划】带权值区间调度问题
- JavaScript进阶--拉勾网鼠标移入移出效果
- 【洛谷 1135】 奇怪的电梯
- android 视频播放的三种方式