资讯专栏INFORMATION COLUMN

前端面试题积累

sunny5541 / 2914人阅读

摘要:构造函数模式问题每个方法都要在每个实例上重新创建一遍。构造函数在不返回值的情况下,默认会返回新对象实例。在默认情况下,所有原型对象都会自动获得一个构造函数属性,这个属性是一个指向属性所在函数的指针。。

创建对象的方式

1、工厂模式

在函数里,new 一个 Object,然后根据传入的参数给该对象添加属性,最后返回该对象。问题:无法知道一个对象的类型。

2、构造函数模式

问题:每个方法都要在每个实例上重新创建一遍。解决:在全局作用域中定义全局函数。当然,这会导致封装性很差。

3、原型模式

每个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象(指向该函数的原型对象),而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。如果按照字面意思来理解,那么 prototype 就是通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。

缺点:原型中所有属性是被很多实例共享的,这种共享对于函数非常合适。但是对于包含引用类型值的属性问题就突出了

4、组合使用构造函数模式和原型模式

构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。
结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。另外,这种混成模式还支持向构造函数传递参数;可谓是集两种模式之长。

5、动态原型模式

在构造函数中这么写共享的方法和属性:

// 方法
if (typeof this.sayName != "function") {
  Person.prototype.sayName = function() {
    alert(this.name);
  };
}

6、寄生构造函数模式

基本思想:创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象。

function Person(name, age, job) {
  var o = new Object();
  o.name = name;
  o.age = age;
  o.job = job;
  o.sayName = function() {
    alert(this.name);
  };
  return o;
}

var friend = new Person("Amy", 18, "student");
friend.sayName();    // Amy

构造函数在不返回值的情况下,默认会返回新对象实例。而通过在构造函数的末尾添加一个 return 语句,可以重写调用构造函数时返回的值。

用法:这个模式可以在特殊的情况下用来为对象创建构造函数。假设我们想创建一个具有额外方法的特殊数组。由于不能直接修改 Array 构造函数,因此可以使用这个模式。

function SpecialArray() {
  // 创建数组
  var values = new Array();
  // 添加值
  values.push.apply(values, arguments);
  // 添加方法
  values.toPipedString = function() {
    return this.join("|");
  };
  // 返回数组
  return values;
}

var colors = new SpecialArray("red", "green", "blue");
alert(colors.toPipedString());    // red|green|blue

关于寄生构造函数模式,有一点需要说明:
首先,返回的对象与构造函数或者与构造函数的原型属性之间没有关系;也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。为此,不能依赖 instanceof 操作符来确定对象类型。

用 new 调用构造函数实际经历了4个步骤

1 创建一个新对象;

2 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);

3 执行构造函数中的代码(为这个新对象添加属性);

4 返回新对象。

理解原型对象

所有函数都有一个 prototype 属性,这个属性指向函数的原型对象

在默认情况下,所有原型对象都会自动获得一个 constructor (构造函数)属性,这个属性是一个指向 prototype 属性所在函数的指针
eg. Person.prototype.constructor => Person。

当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性[[Prototype]]),指向构造函数的原型对象。注意:这个连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。实例 => 构造函数的原型对象

判断某个实例的原型指针是否指向某个函数的原型对象:

Person.prototype.isPrototypeOf(person1)    // true
Object.getPrototypeOf(person1) === Person.protype    // true

hasOwnProperty() 方法:检测一个属性是存在于实例中,还是存在于原型中。只有存在于实例中时,才返回 true。
in 操作符:实例和原型中的属性都能访问到。
同时使用 hasOwnProperty() 方法和 in 操作符,就可以确定该属性到底是存在于对象中,还是存在于原型中。

Object.keys() 方法:取得对象上所有可枚举的实例属性。
Object.getOwnPropertyNames() 方法:得到所有实例属性(包括不可枚举属性)。
重写原型会怎么样?

Person.prototype = {…}:
我们将 Person.prototype 设置为等于一个以对象字面量形式创建的新对象。 最终结果相同,但有一个例外:constructor 属性不再指向 Person 了。前面曾经介绍过,每创建一个函数,就会同时创建它的 prototype 对象,这个对象也会自动获得 constructor 属性。而我们在这里使用的语法,本质上完全重写了默认的 prototype 对象,因此 constructor 属性也就变成了新对象的 constructor 属性(指向 Object 构造函数),不再指向 Person 函数。此时,尽管 instanceof 操作符还能返回正确的结果,但通过 constructor 已经无法确定对象的类型了。

实现继承的方式

1、原型链继承

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95130.html

相关文章

  • 新鲜出炉的8月前端面试

    摘要:前言最近参加了几场面试,积累了一些高频面试题,我把面试题分为两类,一种是基础试题主要考察前端技基础是否扎实,是否能够将前端知识体系串联。 前言 最近参加了几场面试,积累了一些高频面试题,我把面试题分为两类,一种是基础试题: 主要考察前端技基础是否扎实,是否能够将前端知识体系串联。一种是开放式问题: 考察业务积累,是否有自己的思考,思考问题的方式,这类问题没有标准答案。 基础题 题目的答...

    qingshanli1988 评论0 收藏0
  • CSS技巧 - 收藏集 - 掘金

    摘要:笔者作为一位,将工作以来用到的各种优秀资料神器及框架整理在此,毕竟好记性不如烂键盘,此前端知识点大百科全书前端掘金,,不定期更新技巧前端掘金技巧,偶尔更新。计算数组的极值技巧使你的更加专业前端掘金一个帮你提升技巧的收藏集。 CSS 样式画各种图形 - 前端 - 掘金下面是一些我在 CSS 中经常用到的图案,还有一些是在css-tricks看到的。记录一下,以后会用到。会持续更新… 一、...

    Jonathan Shieber 评论0 收藏0
  • CSS技巧 - 收藏集 - 掘金

    摘要:笔者作为一位,将工作以来用到的各种优秀资料神器及框架整理在此,毕竟好记性不如烂键盘,此前端知识点大百科全书前端掘金,,不定期更新技巧前端掘金技巧,偶尔更新。计算数组的极值技巧使你的更加专业前端掘金一个帮你提升技巧的收藏集。 CSS 样式画各种图形 - 前端 - 掘金下面是一些我在 CSS 中经常用到的图案,还有一些是在css-tricks看到的。记录一下,以后会用到。会持续更新… 一、...

    SHERlocked93 评论0 收藏0
  • 2017年3月份前端资源分享

    平日学习接触过的网站积累,以每月的形式发布。2017年以前看这个网址:http://www.kancloud.cn/jsfron... 03月份前端资源分享 1. Javascript 175453545 Redux compose and middleware 源码分析 深入 Promise(二)——进击的 Promise Effective JavaScript leeheys blog -...

    ermaoL 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<