首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

创建从现有对象继承的新对象时的三点JavaScript问题

在JavaScript中,创建从现有对象继承的新对象时可能会遇到以下三个常见问题:

1. 原型链继承的问题

基础概念:原型链继承是通过将子类的原型设置为父类的实例来实现的。

问题:这种方式会导致所有子类实例共享父类实例的属性,这可能会引起意外的副作用。

示例代码

代码语言:txt
复制
function Parent() {
  this.name = 'Parent';
}

Parent.prototype.sayHello = function() {
  console.log('Hello, ' + this.name);
};

function Child() {}

Child.prototype = new Parent(); // 子类的原型设置为父类的实例

var child1 = new Child();
child1.name = 'Child1';
child1.sayHello(); // 输出: Hello, Child1

var child2 = new Child();
child2.sayHello(); // 输出: Hello, Child1,因为name属性被共享了

解决方案:使用Object.create()方法来创建一个新对象,该对象的原型是父类的原型,而不是父类的实例。

代码语言:txt
复制
function Child() {}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child1 = new Child();
child1.name = 'Child1';
child1.sayHello(); // 输出: Hello, Child1

var child2 = new Child();
child2.sayHello(); // 输出: Hello, undefined,避免了属性共享的问题

2. 构造函数继承的问题

基础概念:构造函数继承是通过在子类构造函数中调用父类构造函数来实现的。

问题:这种方式只能继承父类的实例属性和方法,而不能继承父类原型上的方法。

示例代码

代码语言:txt
复制
function Parent(name) {
  this.name = name;
}

Parent.prototype.sayHello = function() {
  console.log('Hello, ' + this.name);
};

function Child(name) {
  Parent.call(this, name); // 调用父类构造函数
}

var child = new Child('Child1');
console.log(child.name); // 输出: Child1
child.sayHello(); // 报错: child.sayHello is not a function

解决方案:结合原型链继承和构造函数继承,以实现完整的继承。

代码语言:txt
复制
function Child(name) {
  Parent.call(this, name); // 调用父类构造函数继承实例属性
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child = new Child('Child1');
console.log(child.name); // 输出: Child1
child.sayHello(); // 输出: Hello, Child1

3. ES6类继承中的问题

基础概念:ES6引入了class关键字,使得继承更加直观和易于理解。

问题:虽然ES6类继承语法简洁,但在某些情况下可能会遇到上下文(this)丢失的问题。

示例代码

代码语言:txt
复制
class Parent {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log('Hello, ' + this.name);
  }
}

class Child extends Parent {
  constructor(name) {
    super(name);
  }

  greet() {
    setTimeout(function() {
      this.sayHello(); // 这里的this指向全局对象,导致错误
    }, 1000);
  }
}

var child = new Child('Child1');
child.greet(); // 报错: this.sayHello is not a function

解决方案:使用箭头函数或者bind()方法来确保this的正确绑定。

代码语言:txt
复制
class Child extends Parent {
  constructor(name) {
    super(name);
  }

  greet() {
    setTimeout(() => {
      this.sayHello(); // 箭头函数自动绑定this
    }, 1000);
  }
}

var child = new Child('Child1');
child.greet(); // 输出: Hello, Child1

以上是创建从现有对象继承的新对象时可能会遇到的三个JavaScript问题及其解决方案。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

JavaScript对象的继承

JavaScript 对象的继承 1. 原型链继承 基于原型链,即把一个对象的原型设置为另一个对象的实例,那么这个对象实例也就拥有了另一个对象上的属性。...借用构造函数 使用父类的实例设置为子类的原型,也就意味着父类的属性变成了子类原型上共享的属性了。我们在之前将面向对象时,说过,对象的属性最好定义在构造函数中,需要共享的引用类型的属性再定义在原型上。...为了解决这个问题,我们可以在子类的构造函数中调用父类的构造函数,这样父类的属性就会变成子类构造函数上的属性,子类的实例对象也就有了独立的属性: function Father() {  this.nationality...person = {  name: "davie",  age: 20 } var p2 = createPerson(person) p2.sayHello() createPerson 方法返回了一个新的对象...一次是在子类构造函数中,一次在创建子类原型的时候。

71320

JavaScript继承的实现方式:原型语言对象继承对象原理剖析

在经典的面向对象语言中,您可能倾向于定义类对象,然后您可以简单地定义哪些类继承哪些类(参考C++ inheritance里的一些简单的例子),JavaScript使用了另一套实现方式,继承的对象函数并不是通过复制而来...“原型对象”是核心概念。原型对象是新对象的模板,它将自身的属性共享给新对象。一个对象不但可以享有自己创建时和运行时定义的属性,而且可以享有原型对象的属性。 ...原型语言创建有两个步骤  使用”原型对象”作为”模板”生成新对象 :这个步骤是必要的,这是每个对象出生的唯一方式。以原型为模板创建对象,这也是”原型”(prototype)的原意。 ...的原型对象上的方法,由于原型重定向,下面的代码会覆盖此方法 Woman.prototype= new People();// 重写原型对象,代之以一个新类型的实例 // 这里实例化一个 People时,...this.subName = subName; } /** 第二步 */ // 解决 call 无法继承父类原型属性/方法的问题 // Object.create 方法接受传入一个作为新创建对象的原型的对象

79120
  • javascript 面向对象(多种创建对象的方式)

    ,但缺点是创建多个对象时,会产生大量的重复代码,因此下面介绍可解决这个问题的创建对象的方法 1、工厂模式 function createPerson(name, age) { var o =...; 2.2 要创建 Person 的新实例,必须使用 new 操作符。...以这种方式调用构造函数实际上会经历以下 4个步骤: (1) 创建一个新对象; (2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象); (3) 执行构造函数中的代码(为这个新对象添加属性...); (4) 返回新对象。...基于以上分析,原型模式创建的对象实例,其属性是共享原型对象的;但也可以自己实例中再进行定义,在查找时,就不从原型对象获取,而是根据搜索原则,得到本实例的返回;简单来说,就是实例中属性会屏蔽原型对象中的属性

    94861

    JS 中对象的简单创建和继承

    Object的属性,并具有obj.x = 1 的属性值 但当参数为null时,obj1则是一个没有原型的新对象,不会继承任何东西,甚至没有初始的toString()方法。...); 对象的简单继承: 可以通过原型继承创建一个新对象 以下函数inherit() 返回一个继承自原型对象p的属性的新对象 function inherit(p){ if(p == null)...f.prototype = p; //原型指向要继承的对象p return new f(); //创建f对象,此对象继承自p } var obj = {x:1}; var obj1...f.prototype = p; //原型指向要继承的对象p return new f(); //创建f对象,此对象继承自p } var o = {}; //o 继承Object.prototype...;在JS中,只有在查询属性时才会体会到继承的存在,而设置属性则和继承无关。

    2.8K20

    javascript 面向对象(实现继承的几种方式)

    this.age = age; }; Parent.prototype = new Person('老明'); //这一句是关键 //通过构造器函数创建出一个新对象...原型中继承来的方法(继承到了当前对象的原型中)   console.log(result.getAge()); //22   //调用了从Parent原型中扩展来的方法 2、构造继承...call、apply 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。...所以,这个借用构造函数就是,new对象的时候(new创建的时候,this指向创建的这个实例),创建了一个新的实例对象, 并且执行Parent里面的代码,而Parent里面用call调用了Person,也就是说把...this指向改成了指向新的实例, 所以就会把Person里面的this相关属性和方法赋值到新的实例上,而不是赋值到Person上面, 所以所有实例中就拥有了父类定义的这些this的属性和方法。

    69180

    JavaScript的几种创建对象的方式

    JavaScript的几种创建对象的方式 工厂模式 构造函数模式 原型模式 组合使用构造函数模式和原型模式(最常见) 动态原型模式 寄生构造函数模式 稳妥构造函数模式 1....return obj; } const person1 = createPerson('litterstar', 18); console.log(person1); 特点: 解决创建多个相似对象的问题...使用 new 来创建实例 缺点: 每次创建实例时,每个方法都要被创建一次 3....Object 参考 JavaScript 创建对象的 7 种方法[1] JavaScript深入之创建对象的多种方式以及优缺点[2] 参考资料 [1]JavaScript 创建对象的 7 种方法: https...://juejin.im/entry/58291447128fe1005cd41c52 [2]JavaScript深入之创建对象的多种方式以及优缺点: https://github.com/mqyqingfeng

    47430

    JavaScript面向对象程序设计—创建对象的模式

    可问题在于,当我想要创建很多很多和上面的person拥有相同结构的对象时,这种方案就不太好了,难道要让我每创建一个对象就要敲一遍name age job sayName吗?...可以看到,一旦我们建好了“工厂”,创建对象就变得很简洁,只不过一行语句的事。这非常不错,但是这种模式仍然不完美,它没办法解决对象识别的问题。...当你在一个函数之前使用new,解析器就知道你是想创建对象,内部就会自动执行以下操作: 1> 创建一个新对象; 2> 将构造函数的作用域赋给这个新对象(因此构造函数中的this会指向这个新对象而不是你以为的...使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。——《JavaScript高级程序设计(第3版)》 什么意思呢?...可以看到,通过原型模式,我们同样可以轻松地创建对象,而且可以像“继承”一般得到我们在原型对象中定义的默认属性,在此基础上,我们也可以对该对象随意地添加或修改属性及值。

    92060

    Oracle创建数据对象时加双引号存在的问题

    问题  一位开发的同事在Oracle中创建表空间A,然后创建用户user_a并指定表空间为A时,提示表空间不存在。...看了他创建表空间的语句之后,发现sql语句类似如下: CREATE TABLESPACE "a" DATAFILE    '/u01/app/oracle/oradata/100G/orcl/users01....dbf' SIZE 5242880   AUTOEXTEND ON NEXT 1310720 MAXSIZE 32767M; 原因分析  由于这个创建表空间的语句是应用程序自动生成的,同时表空间名称是加了双引号的...,在双引号下名称的大小写是敏感的;也就是说 create tablespace a XXX 与create tablespace "a" XXX在数据库中其实是不同的两个对象。...Oracle默认创建的对象是大写的,以下两个语句等价的: CREATE TABLESPACE "A" DATAFILE    '/u01/app/oracle/oradata/100G/orcl/users01

    84120

    JavaScript创建对象的7种模式

    可以无数次地调用这个函数,而每次它都会返回一个包含三个属性一个方法的对象。 工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型) 。...以这种方式调用构造函数实际上会经历以下 4个步骤: (1) 创建一个新对象; (2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ; (3) 执行构造函数中的代码(为这个新对象添加属性...理解原型对象 只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype属性,这个属性指向函数的原型对象。...这个方法 (不要忘了它是从 Object 继承来的)只在给定属性存在于对象实例中时,才会返回 true 。...前面已经解释过了,如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。

    78650

    Javascript面向对象编程(二):构造函数的继承

    这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例。 今天要介绍的是,对象之间的"继承"的五种方法。 比如,现在有一个"动物"对象的构造函数。   ...Cat.prototype = new Animal(); 它相当于完全删除了prototype 对象原先的值,然后赋予一个新值。但是,第二行又是什么意思呢?   ...下文都遵循这一点,即如果替换了prototype对象,   o.prototype = {}; 那么,下一步必然是为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数...所以,上面这一段代码其实是有问题的。...这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。 五、 拷贝继承 上面是采用prototype对象,实现继承。

    1.2K80

    JavaScript 学习-5.对象(object)的创建

    前言 对象(object)是 JavaScript 最重要的数据类型,也是JavaScript的核心内容。JavaScript 中一切皆对象,比如String、 Array、Date等对象。...在 JavaScript 中,对象是非常重要的,当你理解了对象,就可以了解 JavaScript 。...对象有它的属性,如重量和颜色等,方法有启动停止等: 在 JavaScript 中,对象是非常重要的,当你理解了对象,就可以了解 JavaScript 。...创建对象 首先创建一个空的对象,用大括号 var obj = {}; console.log(obj) // {} 创建一个car对象,有三个属性:name,model,color var car =...创建对象 var obj1 = Object.create(null) console.log(obj1) // {} create 在已经有的对象基础上,创建一个新对象 // create 创建对象

    41120

    重学js之JavaScript 面向对象的程序设计(创建对象)

    可以无数次的调用这个函数,而每次它都会返回一个包含三个属性一个方法的对象。工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎么样找到一个对象的类型) 4....另外如果要创建P实例,必须使用 new 操作符,以这种方式调用构造函数实际上会经历以下4个步骤: 创建一个新对象 将构造函数的作用域赋给新对象(因此 this 指向了这个新对象) 执行构造函数中的代码(...通过这个构造函数,我们还可以继续为原型对象添加其他属性和方法。 创建了自定义的构造函数之后,其原型对象默认只会 取得 constructor 属性;至于其他方法,则都是从 Object 继承而来的。...*注意:* 使用动态原型模式时,不能使用对象字面量重写原型,如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。 8....基本概念(中)- 操作符 5、重学js之JavaScript基本概念(下)- 运算符 6、重学js之JavaScript变量、作用域和内存问题 7、重学js之JavaScript引用类型

    1.5K30

    Javascript面向对象编程(三):非构造函数的继承

    这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承"。 今天是最后一个部分,介绍不使用构造函数实现"继承"。 一、什么是"非构造函数"的继承?...'医生'; 这时,子对象已经继承了父对象的属性了。   ...alert(Doctor.nation); //中国 三、浅拷贝 除了使用"prototype链"以外,还有另一种思路:把父对象的属性,全部拷贝给子对象,也能实现继承。...  var Doctor = extendCopy(Chinese);   Doctor.career = '医生';   alert(Doctor.nation); // 中国 但是,这样的拷贝有一个问题...这是早期jQuery实现继承的方式。 四、深拷贝 所谓"深拷贝",就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用"浅拷贝"就行了。

    1.3K50

    重学JavaScript之面向对象的程序设计(继承)

    注意:即在通过原型链实现继承的时候,不能使用对象字面量创建原型方法,因为这样做会重写原型。 6. 原型链的问题 原型链虽然很强大,可以用它来实现继承,但也存在一定的问题。...在通过原型来实现继承时,原型实际上会变成另一个类型的实例。于是,原先的实例属性也就顺理成章地变成了现在的原型属性。 2、在创建子类型的实例时,不能向超类型的构造函数中传递参数。...原型式继承 借助已有的对象创建新对象,先创建一个临时的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的新实例。 10....这样,子类型就能够访问超类型的所有属性和方法。这点和基于类的继承很相似。 原型链的问题就是对象实例共享所有继承的属性和方法,因此不适合单独使用。...8、重学js之JavaScript面向对象的程序设计(创建对象)

    35120

    深入理解JavaScript面向对象的程序设计(一)——对象的创建

    JavaScript面向对象的程序设计(一)——对象的创建 一、Object构造函数 类似Java等面向对象语言中创建对象的语法,在 JavaScript中可以通过执行 new操作符后跟要创建的对象类型的名称来创建...; 直接将属性和方法赋给this对象 没有return语句 要创建Person的新实例,必须使用new操作符,以这种方式调用构造函数,实际上会经过4个步骤: 创建一个新对象; 将构造函数的作用域赋给新对象...) constructor属性是实例从原型中继承过来的属性,虽然从Person、person1和原型中,都可以获取其 constructor的值,但是,constructor不是实例自有的属性。...原型的重写是 JavaScript中使用 prototype实现面向对象中继承的思想的重要依据。...八、其他模式 除了以上7中创建对象的模式外,还有 寄生构造函数模式 和 稳妥构造函数模式 十、下一篇 JavaScript面向对象程序设计(二)——继承 参考资料 《JavaScript高级程序设计

    42610

    JavaScript之面向对象学习六原型模式创建对象的问题,组合使用构造函数模式和原型模式创建对象

    一、仔细分析前面的原型模式创建对象的方法,发现原型模式创建对象,也存在一些问题,如下: 1、它省略了为构造函数传递初始化参数这个环节,结果所有实例在默认的情况下都将取得相同的属性值,这还不是最大的问题!...2、最大的问题是原型中的所有属性是被很多实例所共享的,这种共享对于函数非常合适,对于那些包含基本值的属性也说得过去,因为我们知道可以在实例上添加一个同名属性,可以隐藏原型中的对应属性。...,发现person2同时也被添加了一个朋友,但这并不是我们想要的,而这正是因为原型模式的共享的本性所导致的,只要任何一个实例修改了原型属性对象中的属性值,所有与该原型对象关联的实例都会受到影响!...二、组合使用构造函数模式和原型模式 为了解决原型模式不能初始化参数和共享对于引用模式所存在的问题!...1、构造函数:构造函数创建类型相同的函数,确是不同的作用域链和标识符解析(因为在JS中每创建一个函数就是一个对象,所以  (导致了构造函数中的方法)  在不同的实例中都需要重新创建一遍,但是这些方法做的确实同一件事情

    1.4K60
    领券