首页 > 试题广场 >

说一下类的创建和继承

[问答题]
请讲一下类的创建和继承的具体过程,以及类的继承形式和特点
类的创建方式:
1、工厂模式:在函数里定义一个对象,最后return这个对象。
function app(name,age,job){
    var obj = {
        name: name,
        age: age,
        job: job
    }
    return obj;
  }
var myObj  =  app("bill",32,"engineer");
console.log(myObj.name)   //bill
解决了创建多个相似对象的问题,但没有解决对象识别的问题。也就是说我们无法知道创建出来的对象类型。
2、构造函数模式
构造函数也是函数,只不过可以用来创建对象。要创建构造函数的新实例,必须要用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("bill", 23, "doctor");
var person2 = new Person("lily", 20, "student");
//person1 person2
缺点:每个方法都要在每个实例上重新创建一遍。

3、原型模式:让所有的对象实例共享原型属性和方法。
每个函数都有一个prototype属性,这个属性指向通过调用构造函数创建的那个对象实例的原型对象。Func.prototype --> new Func()的原型对象
function Person(){}
Person.prototype.name = "bill";
Person.prototype.age = 32;
Person.prototype.job = "teacher";

var pers1 = new Person();
var pers2 = new Person();
//pers1与pers2共享Person.prototype上的属性和方法,在一个对象上作原型属性的改变会影响另一个对象。

4、动态原型模式:将信息都封装在构造函数内部,通过条件判断,在必要时再初始化原型。
function Person(name, age,job){
    this.name = name;
    this.age = age;
    this.job = job;
 }
if( typeof this.sayName != "function"){
    Person.prototype.sayName = function(){
        alert(this.name!);
     };
 }
5、寄生构造函数模式:除了用构造函数封装对象,并用new调用该构造函数,其它与工厂模式完全相同。
function Person(name,age,job){
    var obj = {
        name: name,
        age: age,
        job: job
    }
    return obj;
  }
var myObj  =  new Person("bill",32,"engineer");
console.log(myObj.name)   //bill

6、稳妥构造函数模式:与寄生构造函数类似,不同点在于:新创建对象的实例方法不引用this;不适用new操作符调用构造函数。

function Person(name,  age, job){
    var obj = new Object();
    obj.sayName = function(){
     alert(name); 
     }
    return obj;
 }
var friend = Person("bill", 43, "student");
friend.sayname() //稳妥构造函数中,只有此方法可以访问到name属性。
发表于 2019-07-17 16:07:45 回复(0)
一:ES5的构造函数 function Person(name,age){ //构造函数里面的方法和实例 this.name = name this.age = age this.run = function () { console.log(`${this.name}---${this.age}`) } } 这是一个基本的构造函数,run是这个构造函数内的一个方法 注意:Person类的原型链上也有一方法work() Person.prototype.sex= '男' Person.prototype.work = function () { console.log(`${this.name}---${this.sex}`); } 实例化这个构造函数并调用 var p = new Person('zhangsasn',20) p.run(); //张三---20 p.work(); //张三---男 结论:原型链上面的属性和方法通过被多个实例共享 另外ES5中静态方法不需要经过实例化 直接: Person.setName = function () { console.log('静态方法') } //执行静态方法 不需要实例化 Person.setName(); //静态方法 二:ES5中的继承 在ES5的我使用的继承是对象冒充实现继承以及原型链继承相结合 至于为什么要相结合呢? 同样是这个例子 function Person(name,age){ this.name = name this.age = age this.run = function () { console.log(`${this.name}---${this.age}`) } } 我只实现对象冒充继承 function Web(name,age){ Person.call(this,name,age) //对象冒充实现继承 } 这样做有一个缺点:无法继承原型链上属性和方法 比如: Person.prototype.work = function () { console.log('work')//原型链上的实例方法 } var w = new Web() w.work() //undefined 同理我只实现原型链继承 Web.prototype = new Person(); //原型链继承 var w = new Web('李四',20) w.run(); //undefined---undefined 结论:无法把Web子类实例化后的参数传入Person类里面 下面我们正式说一下ES6类的实现 class Person{ constructor(name,age){ this._name = name this._age = age } getName(){ console.log(this._name) } setName(name){ this._name = name } } var p = new Person('张三1','20') p.getName() //张三1 p.setName('李四') p.getName() //李四 这里大家都能看懂吧 不懂的就要回去翻阅一下阮一峰大神的ES6教程 下面就是ES6中的继承 class Person{ constructor(name,age){ this.name = name this.age = age } getInfo(){ console.log(`姓名:${this.name}年龄:${this.age}`); } run(){ console.log('run') } } 使用extends关键字实现继承 class Web extends Person { constructor(name,age,sex){ super(name,age) //实例化Web子类的时候把子类的参数传给父类Person this.sex = sex } print(){ console.log(this.sex) } } var w = new Web('张三','30','男') w.print() //男 w.getInfo() //姓名:张三年龄:30 转载信息 作者:哟哟哟煎饼果子 链接:https://www.jianshu.com/p/17e5e4e0f462 來源:简书
发表于 2019-03-19 18:48:54 回复(0)