标签:src 执行 gre strong var names 设计 想法 images
最近几天跟着视频利用原生的JavaScript做了几个小插件,有图片画廊和图片轮转,实践的过程中,发现对JS的面向对象部分很是陌生,今日重看了《JavaScript高级程序设计》的面向对象部分,并结合了IMOOC网上的《JS深入浅出》教程在此做一下知识的梳理和总结。
ECMA-262中把对象定义为:“无序属性的组合,每个属性包含基本值、对象或者函数。”
对象可以在代码执行过程中创建和增强,因此具有动态性而非严格定义的实体,可以采用下列模式创建对象:
可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法;
可以像创建内置对象实例一样使用new操作符;
function Person(name,age,job){ this.name=name; this.age=age; this.job=job; this.sayName = function(){ alert(this.name); }; } var person1= new Person("Siesta",21,"Student"); var person2 = new Person("Greg",27,"Doctor");
缺点:构造函数的每个成员都无法得到复用,包括函数。由于函数可以不局限于任何对象,因此没有理由不在多个对象共享函数。
使用构造函数的prototype属性来指定那些应该共享的属性和方法。
//isPropertyOf()方法
alert(Person.prototype.isPrototypeOf(person1)); //true alert(Person.prototype.isPrototypeOf(person2)); //true // Object.getPrototype()方法 alert(Object.getPrototypeOf(person1 == Person.prototype) ;//true alert(Object.getPrototypeOf(person1).name); //"Siesta"
单独使用in操作符时,可以通过对象能够访问给定属性时返回true,无论该属性是存在于实例中还是原型中。
function Person(){ } Person.prototype.name="Nicholas"; Person.prototype.age=29; Person.prototype.job="SoftwareEngineer"; Person.prototype.sayName=function(){ alert(this.name); }; var person1=new Person(); var person2=new Person(); alert(person1.hasOwnProperty("name")); alert("name" in person1); //true person1.name="Greg"; alert(person1.name); //"Greg"来自实例 alert(perosn1.hasOwnProperty("name")); //true alert("name" in person1);//true alert(person2.name);//"Nicholas" alert(person2.hasOwnProperty("name"));//false alert("name" in person2);//true delete person1.name; alert(person1.name);//"Nicholas" alert(person1.hasOwnProperty("name"));//false alert("name" in person1);//true
function hasPrototypePrototype(object,name){ return !object.hasOwnProperty(name) && (name in object); }
返回true,则表示存在原型中,返回false,则存在对象中
var keys = Object.getOwnPropertyNames(Person.prototype); alert(keys);
构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。这样,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用。
//组合使用构造函数模式和原型模式 //定义了实例属性的构造函数 function Person(name,age,job){ this.name=name; this.age=age; this.job=job; this.friends=["Shelby","Court"]; } // 定义了共享属性和方法的原型模式 Person.prototype={ constructor:Person, sayName:function(){ alert(this.name); } } var person1=new Person("Nicholas",29,"Software Engineer"); var person2=new Person("Greg",27,"Doctor"); person1.friends.push("Van"); alert(person1.friends);// "Shelby,Court,Van" alert(person2.friends);//"Shelby,Count" alert(person1.friedns == person2.friends); //false alert(person1.sayName == person2.sayName);//true
JavaScript主要通过原型链实现继承。
原型链的构建是通过将一个类型的实例赋值给另一个构造函数的原型实现的。这样,子类型就能够访问超类型的所有属性和方法,这一点与基于类继承很相似。
原型链的问题是对象实例共享所有继承的属性和方法,所以需要利用构造函数,即在子类型构造函数的内部调用超类型构造函数,做到每个实例都具有自己的属性,同时还能保证只使用构造函数来定义类型。
function SuperType(){ this.property=true; } SuperType.prototype.getSuperValue=function(){ return this.property; }; //SuperType类型拥有一个属性和一个方法 function SubType(){ this.subproperty=false; } //继承了Supertype,通过创建SuperType的实例 SubType.property = new SuperType(); SubType.prototype.getSubValue=function(){ return this.subproperty; }; var instance=new SubType(); alert(instance.getSuperValue);
调用instance.getSuperValue()会经历三个搜索步骤:(1)搜索实例;(2)搜索SubType.prototype;(3)搜索SuperType.prototype,最后才会找到该方法,如果找不到属性或方法的情况下,搜索过程总是要一环环地前行到原型链的末端才会停下来。
SubType继承了SuperType,而SuperType继承了Object。当调用instance.toString时,实际上调用的是保存在Object.prototype中的方法。
alert(instance instanceof Object); //true alert(instance instanceof SuperType);//true alert(instance instanceof SubType);//true
2.使用isPrototypeOf()方法,只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型。
alert(Object.prototype.isPrototypeOf(instance);//true alert(SuperType.prototype.isPrototypeOf(instance);//true alert(SubType.prototype.isPrototypeOf(instance);//true
在子类型构造函数内部调用超类型构造函数,通过call()和apply()方法在新创建的对象上执行构造函数
function SuperType(){ this.colors=["red","blue","green"]; } function SubType(){ //继承了SuperType SuperType.call(this); //SuperTyep.apply(this);在新创建的SubType实例的环境下调用了SuperType构造函数 } var instance1=new SubType(); instance1.colors.push("black"); alert(instance1.colors);//"red,blue,green,black" var instance2=new SubType(); alert(instace2.colorss);//"red,blue,green"
相对原型链而言,借用构造函数有一个很大的优势,即可以在子类型构造函数中向超类型构造函数传递参数。
function SuperType(name){ this.name = name; } function SubType(){ //继承了SuperType,同时还传递了参数 SuperType.call(this,Nicholas); this.age=29; } var instance = new SubType(); alert(instance.name);//"Nicholas"; alert(instance.age);//29
也成伪经典继承,指的是将原型链和借用构造函数的技术组合到一块,其想法是使用原型链实现对原型属性和方法的继承,而通过构造函数来实现对实例属性的继承,
//SuperType函数定义了两个属性,name属性和colors function SuperType(name){ this.name=name; this.colors=["red","green","blue"]; } SuperType的原型定义了一个方法sayName(); SuperType.prototype.sayName:function(){ alert(this.name); }; SubType构造函数在调用SuperType构造函数时传入了name参数 function SubType(name,age){ SuperType.call(this.name); this.age=age; } //继承方法 SubType.prototype=new SuperType(); SubType.prototype.constructor=SubType; SubType.prototype.sayAge=function(){ alert(this.age); }; var instance1=new SubType("Nicholas",29); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" instance1.sayName();//"Nicholas" instance1.sayAge();//29 var instance2=new SubType("Greg",27); alert(instance1.colors);//"red,blue,green" instance1.sayName();//"Greg" instance1.sayAge();//27
标签:src 执行 gre strong var names 设计 想法 images
原文地址:http://www.cnblogs.com/siestakc/p/6602656.html