在函数(类)的内部通过this(函数内部自带的一个变量)变量添加属性或者方法来实现对类添加属性或者方法。
通过this添加属性、方法是在当前对象上添加,JavaScript是一种基于原型prototype的语言,每创建一个对象时,都会有一个原型prototype用于指向它继承的属性、方法。
然而通过prototype继承的方法并不是对象本身的,在使用这些方法时,是通过prototype一层一层查找到的。
var book = function(id,bookname,price){ this.id = id; this.bookname = bookname; this.price = price; } book.prototype.display = function(){ //.... } book.prototype = { display:function(){ //执行代码块 } } var bookA = new book(01,'javascript',100) console.log(bookA.bookname)
var Book = function(title,time,type){ //判断执行的this是否是当前对象 if (this instanceof Book) { this.title = title; this.name = name; this.type = type; }else{ return new Book(title,time,type); } } var bookA = Book("CSS3",'2015','css'); console.log(bookA.type)
继承
类的原型对象就是给类原型添加公有方法、属性,但是类不能直接访问这些属性和方法,必须通过原型prototype来访问。
新建的对象复制了父类的构造函数内的属性和方法,并且把原型指向父类的原型对象。这样新建的对象就拥有了父类的原型和方法,该新建的对象可以直接访问到父类原型上的属性和方法。这就是继承。
类式继承
function SuperClass(){ this.superValue = true; } SuperClass.prototype.getSuperValue = function(){ return this.superValue; } function SubClass(){ this.subValue = false; } SubClass.prototype = new SuperClass(); SubClass.prototype.getSubValue = function(){ return this.subValue } var val = new SubClass(); console.log(val.getSuperValue()); //true console.log(val.getSubValue()); //false
使用instanceof来判断前者是否后者(类)的实例。
构造函数继承
function S(id){ this.books = ['javascript',"html","css"]; this.id = id; } S.prototype.showBooks = function(){ console.log(this.books); } //子类 function Sub(id){ S.call(this,id); } var instance1 = new Sub(10); instance1.books.push("javascript"); console.log(instance1.books) console.log(instance1.id)
类式继承是通过子类的原型prototype对父类实例化来实现的,构造函数式继承是通过在子类的构造函数作用环境中执行一次父类的构造函数来实现。
组合继承
function SuperClass(name){ this.name = name; this.books = ["javascript","html","css"]; } SuperClass.prototype.getName = function(){ console.log(this.name); } function subClass(name,time){ SuperClass.call(this,name); this.time = time; } subClass.prototype = new SuperClass(); subClass.prototype.getName = function(){ console.log(this.time) } var bookB = new subClass("java",'2015'); bookB.books.push("CSS3"); console.log(bookB); console.log(bookB.books);
原型继承
function inheritObject(o){ function F(){} F.prototype = o; return new F(); } var book = { name:"javscript", alikeBook:["css","HTML5"] }; var newBook = inheritObject(book); newBook.name = "vue"; newBook.alikeBook.push("ajax"); console.log(newBook.alikeBook);
寄生式继承
就是对原型式继承进行封装,在封装过程中对继承的对象进行拓展。
var bookA = { name: "js", alikeBook: ['html', 'css'] } function createBook(obj) { //通过原型继承的方式来创建新的对象 var o = new inheritObject(obj); //拓展新对象 o.getName = function () { console.log(name) } return o; }
寄生组合式继承(终极者继承)
是寄生式继承和构造函数式继承的组合
/** * 寄生组合式继承 * 终极继承者 * 参数 subClass 子类 * 参数 superClass 父类 */ function inheritPrototype(subClass,superClass){ var p = inheritObject(superClass.prototype); //防止在重写子类原型导致子类的constructor属性被修改 p.constructor = subClass; //设置子类原型 subClass.prototype = p; }
多继承
JavaScript中的继承是依赖于prototype链来实现的,只有一条链。在理论上是不能实现继承多个父类。但是可以通过一些技巧来继承多个多个对象的属性类实现类似的多继承
/** * 类似的多继承 * 单继承 属性复制 * 浅复制过程,只能复制值类型的属性,对于引用类型就无能为力。 */ var extend = function(target,source){ //遍历源对象中的属性 for(var property in source){ target[property] = source[property]; } return target; }; /** * 多继承 属性复制 * 把传入的多个对象属性复制到源对象中, */ var mix = function(){ var i = 1, len = arguments.length, target = arguments[0], arg; //遍历被继承的对象 for(;i < len;i++){ //缓存当前的对象 arg = arguments[i]; //遍历被继承对象的属性 for(var property in arg){ target[property] = arg[property]; } } return target }; Object.prototype.mix = function(){ var i = 0 , len = arguments.length, arg; for(;i<len;i++){ for(var property in arg){ this[property] = arg[property] } } }
多态——多种调用方式
同一个方法多种调用方式,但是必须要对传入的参数做判断而实现多种调用方式。如:
function add(){ var arg = arguments, len = arg.length; switch(len){ case 0: return 10; case 1: return 10+arg[0]; case 2: return arg[0]+arg[1] } } console.log(add()); //10 console.log(add(90)); //100 console.log(add(25,79)) //104
封装和继承是面向对象的两个重要特性,继承就是对源对象的封装,过程中创建私有属性、私有方法、特权方法,共性属性,共有方法。