JS面向对象,原型,继承

ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP)。面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。但是,ECMAScript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。
var box = new Object();
box.name = ‘Lee‘;
box.age = 100;
box.run = function()
{
return this.name + this.age + ‘运行中...‘; //this表示当前作用域下的对象,即new Object()实例化出来的那个对象,this要放在一个作用域下。比如box.run(){}。
}
alert(box.run());

alert(this.name); //这里的this 代表window

工厂模式 解决了重复实例化的问题,但是无法识别对象
function createObject(name,age)
{
var obj = new Object(); //创建对象
obj.name = name; //添加属性
obj.age = age;
obj.run = function(){
return this.name + this.age + ‘运行中...‘;
};
return obj; //返回对象引用
}

var box1 = createObject(‘Lee‘,100);
var box2 = createObject(‘Jack‘,200);
alert(box1.run());
alert(box2.run());

alert(typeof box1);
alert(typeof box2);

构造函数创建对象
function Box(name,age){ //创建一个对象,所有构造函数的对象其实就是Object
this.name = name; //添加一个属性
this.age = age;
this.run = function(){ //添加一个方法
return this.name + this.age + ‘运行中...‘;
};
};
function Desk(name,age){ //创建一个对象,所有构造函数的对象其实就是Object
this.name = name; //添加一个属性
this.age = age;
this.run = function(){ //添加一个方法
return this.name + this.age + ‘运行中...‘;
};
};
//1.构造函数没有new Object,但它后台会自动var obj = new Object
//2.this就相当于obj
//3.构造函数不需要返回对象引用,它是后台自动返回的

//1.构造函数也是函数,但函数名第一个字母大写
//2.必须new构造函数名();new Box(),而这个Box第一个字母也是大写的。
//3.必须使用new运算符。
var box1 = new Box(‘Lee‘,100);
var box2 = new Box(‘Jack‘,200);
var box3 = new Desk(‘kkk‘,500);
alert(box1.run());
alert(box2.run());
alert(box1 instanceof Box);
alert(box2 instanceof Box);
alert(box3 instanceof Desk);

原型
function Box(){} //构造函数函数体内什么都没有,这里如果有,叫做实例属性,实例方法
Box.prototype.name = ‘Lee‘; //原型属性
Box.prototype.age = 100; //原型属性
Box.prototype.run = function(){ //原型方法
return this.name + this.age + ‘运行中...‘;
};
var box1 = new Box();
var box2 = new Box();
alert(box1.name);
alert(box1.run());

//如果是实例方法,不同的实例化,它们的方法地址是不一样的,是唯一的。
//如果是原型方法,那么它们的地址是共享的。
//alert(box1.run == box2.run);  //地址共享,因为box1和box2的run方法都属于Box的原型方法
//alert(box1.prototype); //这个属性是一个对象,访问不到
//alert(box1.__proto__); //这个属性是一个指针指向prototype原型对象,IE浏览器不支持这个属性,打印不出来
//alert(box1.constructor); //构造属性,可以获取构造函数本身。作用是被原型指针定位,然后得到构造函数本身。其实就是对象实例对应的原型对象的作用。

//判断一个对象实例(对象引用)是不是指向了原型对象,基本上,只要实例化,他自动指向的。
//alert(Box.prototype.isPrototypeOf(box1));

//var obj = new Object();
//alert(Object.prototype.isPrototypeOf(obj));

//原型模式的执行流程
//1.先查找构造函数实例里的属性或方法,如果有,立刻返回;
//2.如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回。
//box1.name = ‘Jack‘; //实例属性,并没有重写原型属性,就近原则
//alert(box1.name);
//alert(box2.name); //实例属性不会共享,所以box2访问不到实例属性,只能访问原型属性
//delete box1.name; //删除实例中的属性
//delete Box.prototype.name; //删除原型中的属性
//Box.prototype.name = ‘KK‘; //覆盖原型中的属性
//alert(box1.name);

//box1.name = ‘KAC‘
//alert(box1.hasOwnProperty(‘name‘)); //判断实例中是否存在指定属性
//alert(‘name‘ in box1); //不管实例属性或者原型属性是否存在,只要有就返回true

//判断只有原型中存在属性
//function isProperty(object,property){
//return !object.hasOwnProperty(property) && (property in object)
//}
//alert(isProperty(box1,‘name‘));

function Box(){};
var box = new Box();
alert(box.prototype); //使用对象实例无法访问到prototype
alert(box.__proto__); //使用对象实例访问prototype的指针
alert(Box.prototype); //使用构造函数名(对象名)访问prototype

//使用字面量的方式创建原型对象
function Box(){};
//这里{}就是对象,是Object,new Object就相当于{}
Box.prototype = {
constructor:Box, //强制指向Box
name:‘Lee‘,
age:100,
run:function(){
return this.name + this.age + ‘运行中...‘;
}
};
//使用字面量的方式创建的原型对象会导致constructor指向Object而不是Box
字面量方式创建原型对象的constructor之所以会指向Object是因为Box.prototype={};
这种写法其实就是创建了一个新对象。而每创建一个函数,就会同时创建它的prototype,
这个对象也会自动获取constructor属性。所以,新对象的constructor重写了Box原来的constructor
因此会指向新对象,而新对象没有指定构造函数,那么就是指向Object。

//重写了原型对象
Box.prototype = {
age:200; //这里不会保留之前原型的任何信息了。把原来的原型对象和构造函数对象实例之前的关系切断了。
}
var box = new Box();
//alert(box.constructor == Box);
alert(box.age);

//数组排序
var box = [5,1,6,9,3,5,8,1];
alert(box.sort());

//查看sort是否是Array原型对象里的方法
alert(Array.prototype.sort);
//查看substring是否是String原型对象里的方法
alert(String.prototype.substring);

//内置引用类型的功能扩展
String.prototype.addstring = function(){
return this + ‘,被添加了!‘;
};
var box = ‘Lee‘;
alert(box.addstring());

//原型缺点
function Box(){}
Box.prototype={
constructor:Box,
name:‘Lee‘,
age:100,
family:[‘gege‘,‘jiejie‘,‘meimei‘],
run:function(){
return this.name + this.age + ‘运行中...‘
}
};
var box1 = new Box();
alert(box1.family);
box1.family.push(‘didi‘); //在第一个实例修改后引用类型,保持了共享
alert(box1.family);
var box2 = new Box();
alert(box2.family); //共享了box1添加后的引用类型的原型

//为了解决构造传参和共享问题,可以组合构造函数+原型模式
function Box(name,age){
this.name = name;
this.age = age;
this.family = [‘gege‘,‘jiejie‘,‘meimei‘];
}
Box.prototype = {
constructor:Box,
run:function(){
return this.name + this.age + ‘运行中...‘;
}
};
var box1 = new Box(‘Kee‘,100);
alert(box1.family);
box1.family.push(‘didi‘);
alert(box1.family);
var box2 = new Box(‘lee‘,200);
alert(box2.family); //引用类型没有使用原型,所以没有共享

//动态原型模式,可以将原型封装到构造函数里。封装性更好
function Box(name,age){
this.name = name;
this.age = age;
this.family = [‘gege‘,‘jiejie‘,‘meimei‘];

if(typeof this.run != ‘function‘){ //判断this.run是否存在
//alert(‘KS‘)
Box.prototype.run = function(){
return this.name + this.age + ‘运行中...‘;
};
//alert(‘JS‘);
}
}
//原型的初始化,只要第一次初始化就可以了,没必要每次构造函数实例化的时候都初始化
var box1 = new Box(‘Kee‘,100);
var box2 = new Box(‘lee‘,200);

//寄生构造函数 工厂模式+构造函数
function Box(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name + this.age + ‘运行中...‘;
};
return obj;
}
var box1 = new Box(‘Lee‘,100);
alert(box1.run());
var box2 = new Box(‘Jack‘,200);
alert(box2.run());

//稳妥构造函数
function Box(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name + this.age + ‘运行中...‘;
};
return obj;
}
var box1 = Box(‘Lee‘,100);
alert(box1.run());
var box2 = Box(‘Jack‘,200);
alert(box2.run());

//继承,通过原型链实现
function Box(){ //被继承的函数叫做超类型(父类,基类)
this.name = ‘Lee‘;
}
Box.prototype.name = ‘Jack‘;
function Desk(){ //继承的函数叫做子类型(子类,派生类)
this.age = 100;
}
function Table(){
this.level = ‘AAAAAA‘;
}
//通过原型链继承,超类型实例化后的对象实例,赋值给予类型的原型属性
//new Box()会将Box构造里的信息和原型里的信息都交给Desk
//Desk的原型,得到的是Box的构造+原型里的信息
Desk.prototype = new Box(); //通过原型链继承
Table.prototype = new Desk();
var desk = new Desk();
var table = new Table();
alert(desk.age);
alert(desk.name); //就近原则,实例里有,就返回,没有就去原型查找
alert(table.level);
//子类型从属于自己或者其他的超类型
alert(desk instanceof Desk);
alert(desk instanceof Box);
alert(box instanceof Desk);

//使用对象冒充继承
function Box(name,age){
this.name = name;
this.age = age;
this.family = [‘GEGE‘,‘JIEJIE‘,‘MEIMEI‘]; //引用类型,放在构造里就不会被共享
}
Box.prototype.family = ‘jiating‘;
function Desk(name,age){
Box.call(this,name,age) //对象冒充,只能继承构造里的信息
}
var desk = new Desk(‘Lee‘,100);
alert(desk.name);
alert(desk.family);

//原型链+借用构造函数的模式,这种模式称为组合继承,解决了复用的问题
function Box(name,age){
this.name = name;
this.age = age;
this.family = [‘GEGE‘,‘JIEJIE‘,‘MEIMEI‘];
}
Box.prototype.run = function(){
return this.name + this.age + ‘运行中...‘;
}
//构造函数里的方法,放在构造函数里,每次实例化,都会分配一个内存地址,浪费空间.最好放在原型里,保证多次实例化只有一个地址
function Desk(name,age){
Box.call(this,name,age) //对象冒充
}
Desk.prototype = new Box(); //原型链继承
var desk = new Desk(‘Lee‘,100);
alert(desk.run());

//原型式继承:这种继承借助原型并基于已有的对象创建新对象,同时还不会因此创建自定义类型。
//临时中转函数
function obj(o){ //o表示将要传递进入的一个对象
function F(){} //F构造是一个临时新建的对象,用来存储传递过来的对象
F.prototype = o; //将o对象实例赋值给F构造的原型对象
return new F(); //最后返回这个得到传递过来对象的对象实例
}
//F.prototype = 0其实就相当于Desk.prototype = new Box();
//这是字面量的声明方式,相当于var box = new Box();
var box = {
name:‘Lee‘,
age:100,
family:[‘gege‘,‘jiejie‘,‘meimei‘]
};
//box1就等于new F();
var box1 = obj(box);
//alert(box1.name);
alert(box1.family);
box1.family.push(‘didi‘);
alert(box1.family);
var box2 = obj(box);
alert(box2.family); //引用类型的属性共享了

//寄生式继承 = 原型式+工厂模式
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
//寄生函数
function create(o){
var f = obj(o);
f.run = function(){
return this.name + ‘方法‘;
}
return f;
}
var box = {
name:‘Lee‘,
age:100,
family:[‘gege‘,‘jiejie‘,‘meimei‘]
};
var box1 = create(box);
alert(box1.run());

//寄生组合继承
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
//寄生函数
function create(box,desk){
var f = obj(box.prototype);
f.constructor = desk; //调整原型构造指针
desk.prototype = f;
}
function Box(name,age){
this.name = name;
this.age = age;
}
Box.prototype.run = function(){
return this.name + this.age + ‘ssssss‘;
}
function Desk(name,age){
Box.call(this,name,age); //对象冒充
}
//通过寄生组合继承来实现继承
create(Box,Desk); //这个用来替代Desk.prototype = new Box();
var desk = new Desk(‘Lee‘,100);
alert(desk.run());
alert(desk.constructor);

时间: 2024-10-18 01:41:15

JS面向对象,原型,继承的相关文章

js(面向对象,继承与原型对象)

一.定义: 程序用来描述的生活中的具体事务(对象:是封装一个事物属性与功能的程序结构):主要是用于大程序的维护 二.创建面向对象 1.自定义对象直接量(创建对象) 语法:var obj = { 属性名:属性值, ....:...., 方法名:function(){..this.属性名..}, ... } 举例:var lilei={ sname:"Li Lei", sAge:12, intr:function (){ console.log("I'm "+this.

JS面向对象之继承——原型链

原型对象 每个javascript对象都有一个原型对象,这个对象在不同的解释器下的实现不同.比如在firefox下,每个对象都有一个隐藏的__proto__属性,这个属性就是“原型对象”的引用. 原型链 由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefi

JS面向对象组件 -- 继承的其他方式(类式继承、原型继承)

继承的其他形式: •类式继承:利用构造函数(类)继承的方式 •原型继承:借助原型来实现对象继承对象 类 : JS是没有类的概念的 , 把JS中的构造函数看做的类 要做属性和方法继承的时候,要分开继承. function Aaa(){ //父类 this.name = "小明"; } Aaa.prototype.showName = function(){ alert( this.name ); }; function Bbb(){ //子类 } Bbb.prototype = new

js面向对象之继承-原型继承

//animal 父类 超类 var Animal = function(name) { this.name = name; this.sayhello = function() { alert("HI,我是" + this.name + ",你愿意和我做朋友吗?"); }; }; Animal.prototype.shout = function() { alert(this.name + ",正在叫!"); }; Animal.prototy

Node.js的原型继承函数util.inherits

util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数.JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同.JavaScript 没有 提供对象继承的语言级别特性,而是通过原型复制来实现的,具体细节我们在附录A中讨论, 在这里我们只介绍 util.inherits 的用法,示例如下: var util = require('util'); function Base() { this.name = 'base'

Node.js的原型继承函数 util.inherits

util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数.JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同.JavaScript 没有 提供对象继承的语言级别特性,而是通过原型复制来实现的,具体细节我们在附录A中讨论, 在这里我们只介绍 util.inherits 的用法,示例如下: var util = require('util'); function Base() { this.name = 'base'

js的原型继承小结

考虑:有一个想要复用的对象,并且想要创建的第二个对象需要从第一个对对象中获取其功能. 实现如下: //要继承的对象 var parent = { name:"Papa" }; //新对象 var child = object(parent); console.log(child.name); object函数实现如下: //原型继承 function object(o){ function F(){}; F.prototype = o; return new F(); }; 讨论: 可

JS 面向对象之继承 -- 借用构造函数

转自 http://www.cnblogs.com/yangjinjin/archive/2013/02/01/2889519.html 上次讲到的原型链中,原型链存在一个问题就是不能向超类型的构造函数传递参数.那么这次就是要实现如何向超类型构造函数传递参数. 这种方法我们称之为借用构造函数(constructor stealing) 这里的实现方法是使用js的原生方法apply()或all().那么先温习下apply()和all()函数的知识. call方法: 语法:call([thisObj

JS面向对象-原型对象,实例对象,构造函数的关系

JS中每创建一个函数,该函数就会自动拥有一个prototype属性,为什么那??  因为最根上的object拥有一个prototype属性,而js中所有的对象又都继承自object,所以js中所有的对象都拥有一个prototype属性,而在js中函数也是对象,所以js中每个函数也都有一个prototype属性. 例如:function Person(){...} 和function Dog(){...} 而每一个prototype属性又会获得一个constructor属性 该constructo

JS 面向对象之继承--多种组合继承

转自 http://www.cnblogs.com/yangjinjin/archive/2013/02/01/2889563.html 这一次要讲 组合.原型式.寄生式.寄生组合式继承方式. 1. 组合继承:又叫伪经典继承,是指将原型链和借用构造函数技术组合在一块的一种继承方式. 下面来看一个例子: function SuperType(name) { this.name = name; this.colors = ["red", "blue", "gr