js19--继承终极版本
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Untitled Document</title> <script type=text/javascript charset=utf-8> function extend(Child ,Parent){ var F = new Function();//创建一个函数F,跟写 function F(){};一样 F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child ; //保存一下父类的原型对象: 一方面方便解耦 另一方面方便获得父类的原型对象 Child.superClass = Parent.prototype; //自定义一个子类的静态属性 保存父类的原型对象,写 Child.superClass = Parent也可以。保证子类中可以找到父类。 alert(Parent.prototype.constructor); alert(Parent); /*function Person( name , age){ this.name = name ; this.age = age ; }*/ alert(Parent.prototype.constructor === Parent);//true //判断父类的原型对象的构造器 (加保险),Person.prototype = {中不写constructor: Person ,那么Parent.prototype.constructor就是Object if(Parent.prototype.constructor == Object.prototype.constructor){ Parent.prototype.constructor = Parent ; //容错性,就是写出你不知道的情形。 } } function Person( name , age){ this.name = name ; this.age = age ; } Person.prototype = { sayHello: function(){ alert('hello world!'); } }; Object.defineProperty(Person.prototype , 'constructor' , { enumerable : false , value : Person }); Person.prototype.say = function(){ alert('hello world!'); } function Boy(name , age , sex){ //call,子类就可以直接new Boy(传3个参数),否则只能通过父类实例对象来访问添加的属性。 //Person.call(this,name,age); Boy.superClass.constructor=Person,解耦,子类中不写父类的东西。 Boy.superClass.constructor.call(this , name , age); this.sex = sex ; } extend(Boy , Person); Boy.prototype.sayHello = function(){//覆盖父类的方法 alert('hi javascript!'); } var b = new Boy('张三' , 20 , '男'); alert(b.name); //张三 alert(b.sex);//男 b.sayHello();//hi javascript! //调用父类方法 Boy.superClass.sayHello.call(b);//hello world! b.__proto__.__proto__.sayHello();//hello world! b.constructor.prototype.__proto__.sayHello()//hello world! alert(Boy.superClass.constructor); /*function Person( name , age){ this.name = name ; this.age = age ; }*/ </script> </head> <body> </body> </html>
第一,子类调用call方法。
第二,子类原型对象的构造函数要改变,原型对象和自己对象的构造器指向函数本身(函数本身的prorotype和对象的__proto__指向原型对象)。
第三,子类增加一个静态属性指向父类的原型对象,办证子类可以找到父类。
第四,子类原型对象新增属性要写在creat之后,因为creat之后子类才有了原型对象。
function F(){
this.name = "yw";
var age = 32;
sch = 890;
}
var f = new F();
alert(f.name);//yw
alert(f.age);//undefined
alert(f.sch);//undefined
alert(window.name);//空
F();
alert(window.name);//yw
var F = new Function();//创建一个函数F,跟写 function F(){};一样
//可以直接写constructor,prototype,不能写__proto__,_proto__是为了表示对象是怎么找到类的原型对象的属性方法的。
子类通过prototype访问父类原型对象的属性、方法。
子类通过call访问父类实例对象的属性、方法。不加call方法,访问不到父类实例对象的属性、方法。
父类和对象以静态方式加的属性、方法,子类对象访问不到。