【JS学习笔记】 面向对象与原型

晓石头的博客
邮箱:[email protected]
转载请注明出处,原文链接:http://blog.csdn.net/qiulanzhu/article/details/50583684


/*===================对象的创建======================*/
var box = new Object();	//创建对象
box.name = "Qiu";		//添加属性
box.age = 27;			//添加属性

box.run = function(){
	return this.name + this.age + "运行中<br>";//this指当前作用域下的对象box
};

document.write(box.run());
var name = "jack";
document.write(this.name +"<br>");//这里的this表示window

/*===================相似对象的创建问题======================*/
var box1 = new Object();//创建对象
box1.name = "Qiuyi1";	//添加属性
box1.age = 26;			//添加属性

box1.run = function(){
	return this.name + this.age + "运行中...<br>";//this指当前作用域下的对象box
};

document.write(box1.run())

var box2 = new Object();//创建对象
box2.name = "Qiuyi2";	//添加属性
box2.age = 27;			//添加属性

box2.run = function(){
	return this.name + this.age + "运行中<br>";//this指当前作用域下的对象box
};

document.write(box2.run())


var box3 = box2;		//创建对象
box3.name = "Qiuyi3";	//添加属性
box2.age = 28;			//添加属性
box3.run = function(){
	return this.name + this.age + "运行中<br>";//this指当前作用域下的对象box
};

document.write(box3.run());

//利用工厂模式:解决创建对象的重复操作
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 box4 = createObject('qiu1', 26);
var box5 = createObject('qiu2', 27);
document.write(box4.run() +'<br>');
document.write(box5.run() +'<br>');

function createObject2(name, age){
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	
	obj.run = function(){
		return this.name + this.age + '运行中。。。';
	}
	
	return obj;
}

var box6 = createObject('qiu3', 28);
document.write(box6.run() +'<br>');

document.write(box4 instanceof Object);
document.write(box5 instanceof Object);//都为true,产生识别问题,容易分不清到底是哪个对象的实例
document.write(box6 instanceof Object);

//构造函数:解决创建对象的重复操作、可识别
//1.构造函数默认生成var obj = new Object();
//2.this就相当于obj
//3.构造函数默认返回对象引用

//注意点:
//构造函数的函数名必须大写
//必须使用new运算符
function Box(name, age){
	this.name = name;
	this.age = age;
	
	this.run = function(){
		return this.name + this.age + '运行中。。。<br>';		
	}
}

var box7 = new Box('yi1', 26);
var box8 = new Box('yi2', 27);

document.write(box7.run());
document.write(box8.run());

function Desk(name, age){
	this.name = name;
	this.age = age;
	
	this.run = function(){
		return this.name + this.age + 'ok<br>';
	}
}

var box9 = new Desk('desk', 3);

document.write(box9.run());

document.write(box7 instanceof Box);
document.write(box8 instanceof Box);
document.write(box9 instanceof Desk);//可识别

//对象的比较
var Desk1 = new Desk('desk', 1);
var Desk2 = new Desk('desk', 1);

document.write(Desk1.name == Desk2.name);
document.write(Desk1.run() == Desk2.run());
document.write(Desk1.run != Desk2.run);//比较的是方法的引用地址

//对象冒充(后面会详细讲)
var obj = new Object();
Box.call(obj, 'Box', 2);
document.write(obj.run());

/*===========================原型==========================*/
function Book(){		
	this.name = "Book!";
}
Book.prototype.name = 'book';		//原型属性
Book.prototype.age = 1;

Book.prototype.run = function(){	//不同的对象,原型方法地址共享
	return this.name + this.age +'运行中...';
}

var book1 = new Book();
var book2 = new Book();
document.write(book1.run == book2.run); //共享原型方法地址
document.write(book1.run());

document.write(book1.prototype);
document.write(book2.__proto__);//[object Object]是一个对象
document.write(book2 +'<br>'); 

//构造属性:获取构造函数本身
//构造函数对象 对应的 原型对象
document.write(book1.constructor +"<br>");	

//优先返回实例属性
var book3 = new Book();
document.write(book3.name +"<br>");
document.write(book3.hasOwnProperty("name") +"<br>");
document.write("name in book3:");
document.write("name" in book3);//判断对象中是否有某一属性,不管是原型中还是实例中
delete book3.name;	//删除对象属性
document.write(book3.hasOwnProperty("name") +"<br>");
document.write(book3.name +"<br>");
document.write("name in book3:");
document.write("name" in book3);

//判断是否只是原型中有该属性
function isProperty(obj, property){
	return !obj.hasOwnProperty(property) && (property in obj);
}

var win = new Book();
document.write(isProperty(win, "age") +"<br>");
document.write(isProperty(win, "name") +"<br>");

function Flower(){};
//将原型属性和方法封装,这里的{}就是对象,new Obj();就相当于{};
Flower.prototype = {
	//constructor : Flower,	//强制指向Flower
	name : "rose",
	age : 1,
	run : function(){
		return this.name + this.age + "运行中...";
	}
}
var flower = new Flower();
document.write(flower.prototype +"<br>");//undefined
document.write(flower.__proto__ +"<br>");//[object Object]
document.write(Flower.prototype +"<br>");//[object Object]

document.write(flower.name +"<br>");
document.write(flower.age +"<br>");
document.write(flower.run() +"<br>");

//字面量创建方式:constructor属性指向Objcet(因为字面量创建时有{},相当于new Obj())
//构造函数创建方式:constructor属性指向类
document.write(flower.constructor +"<br>");//function Object() { [native code] }
//怎么让字面量创建方式也指向实例?
//在字面量创建对象里添加:constructor : Flower,

//重写原型函数,之前的原型属性和方法都会消失
Flower.prototype = {
	name : "sun",
}

var sun = new Flower();
document.write(sun.name);
document.write(sun.age +"<br>");


//内置类的原型
//数组排序
var box = [4,3,5,3,6,1,4,9,0];
document.write(box.sort() +"<br>");
//查看Array原型里的方法
document.write(Array.prototype.sort +"<br>");
//查看String原型里的方法
document.write(String.prototype.substring +"<br>");
//新增String原型方法(内置类型的功能扩展)
String.prototype.addString = function(){
	return this + ",追加字符串!<br>";
}
document.write("qiuyi".addString());

//原型的缺点
//1.字面量创建不灵活,没有办法通过传参改变属性值
//2.共享导致的问题

//为了解决构造传参和共享问题,采用:构造函数 + 原型模式。

function Fruit(name, weight){
	this.name = name;
	this.weight = weight;
	this.shape = ["方","圆","扁"];
}

Fruit.prototype = {
	constructor : Fruit,
	run : function(){
		return this.name + this.weight;
	}
}

var fruit = new Fruit("苹果", 5);
document.write(fruit.run());

//动态原型模式,将原型封装到构造函数类
function Fruit1(name, weight){
	this.name = name;
	this.weight = weight;
	this.shape = ["方","圆","扁"];
	
	if( typeof(this.run) != "function" ){
		Fruit1.prototype.run = function(){
			return this.name + this.weight;
		}
	}
}

var fruit1 = new Fruit1("苹果", 5);
document.write(fruit1.run());

//寄生构造函数:构造函数+工程模式。---很通用
function Moon(name, age){	//类名大写
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	obj.run = function(){
		return this.name + this.age;
	}
	return obj;
}

//稳妥构造函数:构造函数例不能用this,函数外不能用new
function Sum(name, age){	//类名大写
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	obj.run = function(){
		return this.name + this.age;
	}
	return obj;
}

var isSum = Sum("sun", 1000);

/*============================原型链接继承================================*/
//通过原型链实现
//有个问题:1.无法传参,
function Ball(){
	this.name = "qiu";
}

function Basketball(){
	this.age = 2;
}

Basketball.prototype = new Ball();//通过原型链继承:超类实例化后的对象,赋值给子类的原型属性
var myBall = new Basketball();
document.write(myBall.name +"<br>");

/*============================对象冒充继承==================================*/
//解决:1.可以传参
//但有一个问题:无法继承基类的原型属性(方法一般放在原型里,多个对象只需要一份。这样对象冒充就无法继承到这个方法了。)
function Good(name, age){
	this.name = name;
	this.age = age;
}

function Better(name, age){
	Good.call(this, name, age);
}

var myState = new Better("yi", 27);
document.write(myState.name +"<br>");


/*==============================原型链+对象冒充=============================*/
//最常用的继承方式
//有个小问题:调用父类两次
function Big(name, age){
	this.name = name;
	this.age = age;
}

function Bigger(name, age){
	Big.call(this, name, age);		//对象冒充继承
}

Bigger.prototype = new Big();		//原型链继承

var myBigger = new Bigger("qiuyi", 27);
document.write(myBigger.name);

/*==============================原型式继承:和原型链继承一样,只是变化了结构=================================*/
//存在共享问题,一个对象改了原型属性,所有对象的都变了。
//临时中转函数
function objtest(o){				//o为传入的对象
	function Fun(){};			
	Fun.prototype = o;			//将对象o赋值给F的原型对象,等价与Fun.prototype = new Obj();
	return new Fun();
}

//字面量的申明方式,类似与var box = new Box();
var myobj = {
	name : "qiuyi",
	age : 27,
	family : ["哥哥", "弟弟", "妹妹"]
}

var firstBox = objtest(myobj);
document.write(firstBox.family);


/*==============================寄生式继承:原型式 + 工厂模式=================================*/
//临时中转函数
function objfirst(o){				//o为传入的对象
	function Fun(){};			
	Fun.prototype = o;			//将对象o赋值给F的原型对象,等价与Fun.prototype = new Obj();
	return new Fun();
}

//寄生函数
function createfirst(o){
	var funcfirst = objfirst(o);
	funcfirst.run = function(){
		return this.name + "方法";
	}
	
	return funcfirst;
}

var myobjfirst = {
	name : "qiuyi",
	age : 27,
	family : ["哥哥", "弟弟", "妹妹"]
}

var first1 = createfirst(myobjfirst);
document.write(first1.run());

/*==============================寄生组合继承=================================*/
//解决原型链+对象冒充的调用基类两次的问题
//临时中转函数
function tmpObj(o){				//o为传入的对象
	function Fun(){};			
	Fun.prototype = o;			//将对象o赋值给F的原型对象,等价与Fun.prototype = new Obj();
	return new Fun();
}

//寄生函数
function create(Animal, Cat){
	var fun = tmpObj(Animal.prototype);
	fun.constructor = Cat;			  //调节构造指针
	Cat.prototype = fun;
//	Cat.prototype = Animal.prototype; //为什么不直接用这一句呢?
}


function Animal(name, age){
	this.name = name;
	this.age = 27;
	
	if( typeof(this.run) != "function" ){
		Animal.prototype.run = function(){
			return this.name + this.age + "running...<br>";
		}
	}
}


function Cat(name, age){				//对象冒充继承
	Animal.call(this, name, age);
}

create(Animal, Cat);					//原型式继承

var myCat = new Cat("mao", 5);
document.write(myCat.run());


你可能感兴趣的:(【JS学习笔记】 面向对象与原型)