对象具有三大特性:封装,继承,多态
一、封装
1.函数的封装是为了函数的安全性,将对象进行包装,通过有限的接口衍化不同的对象
2.工厂函数封装
工厂函数是设计模型中的一种说法,不是通过类实例化构造函数,而是通过函数进行构造对象,在函数内部创建一个对象,通过参数的传递实现对象的更多控制,并将对象返回,当属性相同时造成内存的浪费。
// (函数里创建一个对象,对象的属性值由自己传入,) function person(name,age,say){ var obj ={}; obj.name=name; obj.age=age; obj.say=say; //回调 return obj; } function say1 (){ alert('说话') } function say2 (){ alert('笑') } var ls =person('ls',16,say2); //(不需构造函数,接收的返回值本身就是对象) var zs =person('zhangsan',18,say1); // (zs变为对象,接收工厂函数的返回值)
3.构造函数封装
function person(name,age){ this.name=name; this.age=age;}person.prototype.say=function(){ alert("说话")}var zs=new person("zs",12);var ls=new person("ls",15);zs.say();ls.say();
console.log(ls instanceof Object) //true console.log(ls instanceof person) //true
//公用代码段放在prototype原型中存储,其属性是固定的,不可改变
4.构造函数与工厂函数的异同
1)工厂函数需要创建对象,并且必须有返回值
2)工厂函数针对的是Object的对象模型,而构造函数可以匹配自定义的对象模型
3)工厂函数只能在局部添加新的属性和方法,构造函数可重写,在全局中添加新属性和方法
4)构造函数在全局中定义相同的局部变量,容易造成全局污染,this.xx在局部中获取不到,就会去全局中获取。
二、继承(实现代码的重复使用)
1.继承的原理:拷贝
1)深拷贝:拷贝对象的值
2)浅拷贝:拷贝对象的地址,影响源对象的属性值
var json={name:"zhangsan",age:12,son:{name:"lisi"}} var json1=copy(json) //浅拷贝 function copy(json){ var newobj={} for(var i in json){ newobj[i]=json[i] } return newobj; } json1.son.name="lisi1" console.log(json.son.name) //lisi1 //深拷贝 function copy(json){ var newobj={}; for(var i in json){ if(typeof json[i]=="object"){ newobj[i]=copy(json[i]) }else{ newobj[i]=json[i] } } return newobj } json1.son.name="lisi1" console.log(json.son.name) //lisi
2.ES6继承
class fun{ constructor(){ this.name="zhangsan" } done(){ console.log(this.name) } } class stu extends fun{ //extends 实现继承 constructor(){ super(); //将父类的this继承到子级中 } done(){ return this.name } } var obj=new stu(); console.log(obj.done())
3.js继承方式
1)原型继承
//父类function people() { this.say=function () { alert("父级的属性") }}people.prototype.done=function () { console.log("原型上的属性")}//子类function stu() { this.age=10;}//原型继承//核心:子类在原型上继承父类的实例stu.prototype=new people() //先继承再调用var obj=new stu("继承")obj.say()obj.done()//可继承父类原型上的属性与方法
特点:父类新增的原型方法和属性,子类都可访问
简单,易于实现
缺点:想要为子类新增属性和方法,必须在new 语句之后执行,不能放在构造函数中
无法实现多继承
来自原型对象的引用属性是所有实例共享的
创建子类实例时,无法向父类构造函数传参
2)call aplay 冒充
//父类function people(str) { this.say=function () { alert(str) } } people.prototype.done=function () { console.log("原型上的属性") } //子类 function stu() { }//call apply //核心:改变this指针var obj=new stu()people.call(obj,"继承")people.apply(obj,["继承"])obj.say()obj.done()//报错,无法继承父类原型上的属性
三、多态
对象灵活多变,可通过参数控制实现不同的功能
四、Object
1.Object是js的顶层对象,任何对象都可看做由Object实例化而来。
2.构造函数constructor
当任意一个普通函数用于创建一个对象的时候,就称为构造函数,构造函数可在函数内部对新对象(this)的属性进行设置,通常是添加属性和方法
3.检测某个构造函数是否为对象的实例化
function father() {}function son() {}son.prototype=new father();var ls=new son()console.log(ls instanceof son) //trueconsole.log(ls instanceof father) //true//检测某个构造函数是否为对象的实例化,实质上是看对象是否在构造函数的原型链上
3.原型prototype
在js中每定义一个对象(函数),对象中都会包含一些预定义的属性,其中函数对象的一个属性就是原型对象 prototype。注:普通对象没有prototype,但有__proto__属性。在js继承规则中,实例化出来的对象能够继承构造函数Prototype属性身上的属性与方法。
原型链
JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型对象prototype。
function obj() { }var aa=new obj()console.log(aa.__proto__===obj.prototype); //trueconsole.log(obj.prototype.__proto__===Object.prototype);//trueconsole.log(Object.prototype__proto__) //undefined 顶层对象,继承达到顶端
**1.原型和原型链是JS实现继承的一种模型。
2.原型链的形成是真正是靠__proto__ 而非prototype3.任何对象都有一个__proto__属性,任何函数对象(除了Function)都有一个prototype属性
4.new 操作符实例化对象
function Obj(){ }var obj=new Obj()//1.var obj=new Object() 内部创建空对象,所有对象都是由Object new出的对象//2.obj.__proto__指向构造函数Obj.prototype //Obj.prototype.__proto__指向构造函数Object.prototype //Object.prototype.__proto__//3.Obj.call(obj) 改变this指针方向//4.return obj; 创建对象完成
5.继承顺序
参考:http://www.cnblogs.com/wangyingblog/p/5583825.html
http://www.108js.com/article/article1/10201.html?id=1092
function person(){ this.say=function(){ alert("person上的方法") } } person.prototype.say=function(){ alert("person原型上的方法") } function student(){ this.say=function(){ alert("student上的方法") } } student.prototype.say=function(){ alert("student原型上的方法") } student.prototype=new person(); var zs=new student() zs.say()//先继承构造函数本身的属性,再继承原型上的属性//子类继承的父类属性会覆盖子类原型上的属