1、什么是原型?
答:“照猫画虎”,这里的猫就是虎的原型。JavaScript是利用原型来描述对象。 2、什么是基于原型? 答:基于原型的面向对象系统是通过“复制”的方式来创建新对象。这种操作有两种实现思路: 一是并不是真的去复制一个原型对象,而是使得新对象持有一个原型的引用; 另一个是切实地复制对象,从此两个对象再无联系。 显然,JavaScript使用了第一种方式。 3、JavaScript的原型 答:简单概括就是: 如果所有对象都有私有字段[[prototype]],就是对象的原型; 读一个属性,如果对象本身没有,则会继续访问对象后的原型,知道原型为空或者找到为止。 4、ES6提供的内置函数,方便直接访问操纵原型: 答:Object.create 根据指定的原型创建新对象,原型可以是 null; Object.getPrototypeOf 获得一个对象的原型; Object.setPrototypeOf 设置一个对象的原型。 var cat = { say(){ console.log("meow~"); }, jump(){ console.log("jump"); } } var tiger = Object.create(cat, { say:{ writable:true, configurable:true, enumerable:true, value:function(){ console.log("roar!"); } } }) var anotherCat = Object.create(cat); anotherCat.say(); var anotherTiger = Object.create(tiger); anotherTiger.say(); 这段代码创建了一个“猫”对象,又根据猫做了一些修改创建了虎,之后我们完全可以用 Object.create 来创建另外的猫和虎对象,我们可以通过“原始猫对象”和“原始虎对象”来控制所有猫和虎的行为。 5、那虎这个类的say方法里怎么取调用猫的say方法呢?是不是在方法里实例一个猫对象去掉用猫.say()?这样一来就多生产一个对象了。如果继承有很多层的会多出很多实例呢? 答:Object.getPrototypeOf(Object.getPrototypeOf(anotherTiger)).say(); 6、早期版本中的类与原型。 答:在早期版本的 JavaScript 中,“类”的定义是一个私有属性 [[class]],语言标准为内置类型诸如 Number、String、Date 等指定了[[class]]属性,以表示它们的类。语言使用者唯一 可以访问[[class]]属性的方式是 Object.prototype.toString。 7、为什么object.prototype.tostring是最准确的判断数据的方法。 答:js中私有属性不可更改,且只有这个方法可以访问。 8、以下代码展示了所有具有内置 class 属性的对象: 9、new操作具体做了哪些操作? 答:new 运算接受一个构造器和一组调用参数,实际上做了几件事: 以构造器的 prototype 属性(注意与私有字段[[prototype]]的区分)为原型,创建新对象; 将 this 和调用参数传给构造器,执行; 如果构造器返回的是对象,则返回,否则返回第一步创建的对象。 new 这样的行为,试图让函数对象在语法上跟类变得相似,但是,它客观上提供了两种方式,一是在构造器中添加属性,二是在构造器的 prototype 属性上添加属性。 10、下面的代码展示了使用构造器来模拟类的两种方法: function c1(){ this.p1 = 1; this.p2 = function(){ console.log(this.p1); } } var o1 = new c1; o1.p2(); function c2(){ } c2.prototype.p1 = 1; c2.prototype.p2 = function(){ console.log(this.p1); } var o2 = new c2; o2.p2(); 第一种方法是直接在构造器中修改 this,给 this 添加属性。 第二种方法是修改构造器的 prototype 属性指向的对象,它是从这个构造器构造出来的所有对象的原型。 11、ES6中的类 答:ES6中新特性class关键字,类的概念正是从属性升级为语言的基础设施。类的编程方式成为了JavaScript的官方编程范式。 类的基本写法: class Rectangle { constructor(height, width) { this.height = height; this.width = width; } // Getter get area() { return this.calcArea(); } // Method calcArea() { return this.height * this.width; } } 我们通过 get/set 关键字来创建 getter,通过括号和大括号来创建方法,数据型成员最好写在构造器里面。不建议在constructor之外定义属性。 12、类的写法实际上是有原型运行时来承载的,逻辑上JavaScript认为每个类是有共同原型 的一组对象,类中定义的属性和方法会被写在原型对象之上。 最重要的是,类提供了继承能力。 class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } class Dog extends Animal { constructor(name) { super(name); // call the super class constructor and pass in the name parameter } speak() { console.log(this.name + ' barks.'); } } let d = new Dog('Mitzie'); d.speak(); // Mitzie barks. super() 实际上相当于Parent.prototype.constructor.call(this) 使用 extends 关键字自动设置了 constructor,并且会自动调用父类的构造函数,这是一种更少坑的设计。 |
|