资讯专栏INFORMATION COLUMN

JavaScript高级程序设计-摘要笔记-3

AndroidTraveler / 1127人阅读

摘要:如果重设构造函数的原型对象,那么,会切断新的原型对象和任何之前已经存在的构造函数实例之间的联系,它们引用的仍然是最初的原型。说明返回的对象与构造函数或者与构造函数的原型属性没有关系。

说明:

此摘要笔记系列是我最近看《JavaScript高级程序设计(第3版)》随手所记。
里面分条列举了一些我认为重要的、需要记下的、对我有帮助的点,是按照我看的顺序来的。
摘要笔记本身没有系统性,没有全面性可言,写在这里供有一定基础的前端开发者参考交流。
里面的知识点、例子大部分来源于本书,或者延伸出来的,都经过我的测试是对的,但是没办法保证100%正确,如果有人看到错误的地方,希望指出来,谢谢。

对象原型的其它模式 1. 更简单的原型语法
a. 重写构造函数的 prototype 属性

用这种方法如果不设置原型的 constructor 属性,则原型的 constructor 属性跟普通对象一样,指向 Object,
如:

var Person = function () {}
Person.prototype = {
  name: "abc",
  sayHello: function () {
    console.log("hello")
  }
}
Person.prototype.constructor === Person // false
Person.prototype.constructor === Object // true

var ming = new Person()
ming.constructor === Person // false
ming.constructor === Object // true
ming.__proto__ === Person.prototype // true
ming instanceof Person // true
b. 设置原型的 constructor 属性

之后的表现跟在原生的原型对象上添加属性一样,
如:

var Person = function () {}
Person.prototype = {
  constructor: Person,
  name: "abc",
  sayHello: function () {
    console.log("hello")
  }
}
Person.prototype.constructor === Person // true

var ming = new Person()
ming.constructor === Person // true
ming.__proto__ === Person.prototype // true
ming instanceof Person // true

但是,重设 constructor 属性会导致它的 [[Enumerable]] 特性被设置成 true,变成可枚举的。
这个问题可以用 Object.defineProperty() 来改正。
如:

var Person = function () {}
Person.prototype = {
  name: "abc",
  sayHello: function () {
    console.log("hello")
  }
}
Object.defineProperty(Person.prototype, "constructor", {
  enumerable: false,
  value: Person
})
2. 原型的动态性

如果不重设构造函数的 prototype 原型对象,那么,我们对原型对象的任何修改都能够反映到实例上,即使先创建实例后修改原型。

如果重设构造函数的 prototype 原型对象,那么,会切断新的原型对象和任何之前已经存在的构造函数实例之间的联系,它们引用的仍然是最初的原型。

3. 组合使用构造函数模式和原型模式

创建自定义类型的最常用方式,就是组合使用构造函数模式和原型模式。构造函数用于定义实例属性,原型模式用于定义方法和共享的属性。

好处:每个实例都会有自己的实例属性的副本,同时又共享着对方法的引用,最大限度的节省了内存。
还支持向构造函数传递参数。
如:

function Person (name, age) {
  this.name = name
  this.age = age
  this.friends = ["Ming", "Li"]
}
Person.prototype = {
  constructor: Person,
  sayName: function () {
    console.log(this.name)
  }
}

var zhang = new Person("zhang", 12)
var yang = new Person("yang", 15)
zhang.friends.push("wang")
console.log(zhang.friends) // ["Ming", "Li", "wang"]
console.log(yang.friends) // ["Ming", "Li"]
zhang.sayName === yang.sayName // true
4. 动态原型模式

如:

function Person (name, age) {
  this.name = name
  this.age = age
  if (typeof this.sayName !== "function") {
    Person.prototype.sayName = function () {
      console.log(this.name)
    }
  }
}
// 注意在用这种模式时,不能使用对象字面量重写原型。
5. 寄生构造函数模式

这种模式的基本思想就是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象。但从表面看,这个函数很像构造函数。
如:

function Person (name, age) {
  var person = {
    name: name,
    age: age,
    sayName: function () {
      console.log(this.name)
    }
  }
  return person
}

var ming = new Person("ming", 12)
ming.sayName() // "ming"
ming instanceof Person // false
ming instanceof Object // true
ming.__proto__ === Object.prototype // true
ming.constructor === Object // true

注意:这个模式除了使用new操作符并把包装的函数叫做构造函数外,跟工厂模式是一摸一样的。
说明:返回的对象与构造函数或者与构造函数的原型属性没有关系。

6. 稳妥构造函数模式

(因为不使用new操作符,所以函数名称就不首字母大写了)

稳妥构造函数模式与寄生构造函数类似,但有两点不同:一是新创建的实例方法不引用this;二是不使用new操作符调用构造函数。
如:

function person (name, age) {
  var o = {}
  o.sayName = function () {
    console.log(name)
  }
  return o;
}
var ming = person("ming", 12)
ming.sayName() // "ming"
ming instanceof person // false
ming instanceof Object // true

注意:在这里除了调用 sayName 方法,没有其它办法访问 name 的值
说明:同寄生构造函数模式,返回的对象与构造函数或者与构造函数的原型属性没有关系。

关于对象原型部分结束。下一篇是继承相关的内容

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

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

相关文章

  • JavaScript高级程序设计摘要笔记-6

    摘要:关于对象定义了全局对象。支持的浏览器有除了接受要序列化的对象外,还可以接受另外两个参数。如果是数值,则表示每个级别缩进的空格数,最大,超过的值自动转换成。字符串长度超过,结果中将只出现前个字符。会在结果字符串中插入换行符提高可读性。 关于JSON 1. JSON 对象 es5 定义了全局对象 JSON。支持的浏览器有 IE8+ 、Firefox 3.5+ 、Safari 4+、Chro...

    Batkid 评论0 收藏0
  • JavaScript高级程序设计摘要笔记-1

    摘要:说明此摘要笔记系列是我最近看高级程序设计第版随手所记。摘要笔记本身没有系统性,没有全面性可言,写在这里供有一定基础的前端开发者参考交流。对每一项运行给定函数,返回该函数会返回的项组成的数组。是的反操作是的反操作第一部分结束。 说明: 此摘要笔记系列是我最近看《JavaScript高级程序设计(第3版)》随手所记。 里面分条列举了一些我认为重要的、需要记下的、对我有帮助的点,是按照我看...

    chavesgu 评论0 收藏0
  • JavaScript高级程序设计摘要笔记-5

    摘要:函数表达式和闭包函数声明的一个重要特征是函数声明提升如递归递归函数是在一个函数通过名字调用自身的情况下构成的。注意中已经是块级作用域了,所以这些东西感觉实际用途没有那么大,但是对理解闭包对作用域链中的属性的引用,这一点还是有作用的。 函数表达式和闭包 1. 函数声明的一个重要特征是函数声明提升 如: sayHi() function sayHi () { console.log(h...

    JerryWangSAP 评论0 收藏0
  • JavaScript高级程序设计摘要笔记-4

    摘要:思路是,使用原型链对原型属性和方法进行继承,借用构造函数实现对实例属性的继承。注意使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率,这一点与构造函数模式类似。无论什么情况下都会调用两次超类型的构造函数。 说明: 此摘要笔记系列是我最近看《JavaScript高级程序设计(第3版)》随手所记。里面分条列举了一些我认为重要的、需要记下的、对我有帮助的点,是按照我看的顺序来的...

    zr_hebo 评论0 收藏0
  • JavaScript高级程序设计摘要笔记-2

    摘要:说明此摘要笔记系列是我最近看高级程序设计第版随手所记。其中,描述符对象的属性必须是设置其中一个或多个值,可以修改对应的特性值。如支持的浏览器,可以取得指定属性的描述符。 说明: 此摘要笔记系列是我最近看《JavaScript高级程序设计(第3版)》随手所记。里面分条列举了一些我认为重要的、需要记下的、对我有帮助的点,是按照我看的顺序来的。摘要笔记本身没有系统性,没有全面性可言,写在这里...

    roland_reed 评论0 收藏0

发表评论

0条评论

AndroidTraveler

|高级讲师

TA的文章

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