JS面向对象,原型,继承
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
以上是关于JS面向对象,原型,继承的主要内容,如果未能解决你的问题,请参考以下文章