资讯专栏INFORMATION COLUMN

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

roland_reed / 2234人阅读

摘要:说明此摘要笔记系列是我最近看高级程序设计第版随手所记。其中,描述符对象的属性必须是设置其中一个或多个值,可以修改对应的特性值。如支持的浏览器,可以取得指定属性的描述符。

说明:

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

1. Math 对象
Math.E // 2.718281828459045 自然对数的底数,即常量 e 的值
Math.PI // 派的值 3.141592653589793
Math.min() // 一组数中的最小值
Math.max() // 一组数中的最大值
// 取得数组中最大值的办法
var arr = [10, 15, 8, 23]
var max = Math.max.apply(Math, arr)
console.log(max) // 23
Math.ceil() // 向上取整
Math.floor() // 向下取整
Math.round() // 四舍五入取整
Math.random() // 返回大于等于0小于1的随机数
Math.abs(num) // 返回 num 的绝对值
Math.log(num) // 返回 num 的自然对数
Math.pow(num, power) // 返回 num 的power次幂
Math.sqrt(num) // 返回 num 的平方根
Math.cos(x) // 返回 x 的余弦值
Math.sin(x) // 返回 x 的正弦值
Math.tan(x) // 返回 x 的正切值
Math.acos(x) // 返回 x 的反余弦值
Math.asin(x) // 返回 x 的反正弦值
Math.atan(x) // 返回 x 的反正切值
Math.atan2(y, x) // 返回 y / x 的反正切值
2. 深度拷贝对象的简单高效办法
var rel = JSON.parse(JSON.stringify(obj))
3. Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象Object.assign(target, ...sources),如:
var obj = {a: 1}
var copy = {b: 3}
var rel = Object.assign(b, obj)
console.log(rel) // {a: 1, b: 3}
copy === rel // true

假如需要深度拷贝的话,仍旧需要使用别的而不是本方法。因为 Object.assign() 拷贝的是在 source 里是对象的属性的引用而不是对象本身。如:

var a = {b: 3, c: {e: 5}}
var rel = Object.assign({}, a)
console.log(rel.c.e) // 5
a.c.e = 8
console.log(rel.c.e) // 8
// 合并 objects
var o1 = {a: 2}
var o2 = {b: 5}
var o3 = {c: 8}
var rel = Object.assign(o1, o2, o3)
console.log(rel) // {a: 2, b: 5, c: 8}
console.log(o1) // {a: 2, b: 5, c: 8}
rel === o1 // true
// 继承属性和不可枚举属性是不能拷贝的
// 原始类型会被包装为 object
4. 对象的属性

ECMAScript 中有两种属性:数据属性和访问器属性

a. 数据属性:数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述其行为的特性。
[[Configurable]]: 能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。默认 true 。
[[Enumerable]]: 能否通过 for-in 循环返回属性。默认 true 。
[[Writable]]: 能否修改属性的值。默认 true 。
[[Value]]: 包含这个属性的数据值。读取属性的时候从这个位置读;写入属性值的时候,把新值保存在这个位置。默认值 undefined 。

要修改属性默认的特性,需要通过 es5 的 Object.defineProperty() 方法。这个方法接受三个参数,属性所在的对象,属性的名字和一个描述符对象。
其中,描述符 (descriptor) 对象的属性必须是:configurable, enumerable, writable, value. 设置其中一个或多个值,可以修改对应的特性值。如:

var person = {}
Object.defineProperty(person, "name", {
  writable: false,
  value: "abc"
})
person.name // "abc"
person.name = "wfc" // 严格模式下会报错
person.name // "abc"

在调用 Object.defineProperty() 方法时,如果不指定,configurable, writable, enumerable 的默认值都是 false。

可以多次调用 Object.defineProperty() 来修改同一个属性,但是在把 configurable 特性设置为 false 之后,
就只能把 writable 从 true 改成 false,其它设置都会报错。

b. 访问器属性

访问器属性不包含数据值,它们会包含一对 getter setter 函数(都不是必须的)。在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值;
在写入访问器属性时,会调用 setter 函数并传入新值,这个函负责决定如何处理数据。访问器属性有如下4个特性:

[[Configurable]]: 表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。
对于直接在对象上定义的属性,默认值 true 。
[[Enumerable]]: 表示能否通过 for-in 循环返回属性。对于直接在对象上定义的属性,默认值 true 。
[[Get]]: 在读取属性时调用的函数。默认值 undefined 。
[[Set]]: 在写入属性时调用的函数。默认值 undefined 。

访问器属性不能直接定义,必须使用 Object.defineProperty() 来定义。如:

var book = {
  _year: 2016,
  edition: 1
}
Object.defineProperty(book, "year", {
  get: function () {
    return this._year
  },
  set: function (newValue) {
    this.edition += 1
    this._year = newValue
  }
})
book.edition // 1
book.year = 2017
book.edition // 2

不必要同时指定 getter setter , 只指定 getter 意味着属性不能写,只指定 setter 意味着属性不能读

// 支持 Object.defineProperty() 的浏览器 IE 9+,Firefox 4+, Safari 5+, Opera 12+, Chrome
5. Object.defineProperties() 可以通过描述符一次定义多个属性。这个方法接受两个参数,第一个参数是要添加和修改其属性的对象,

第二个参数是描述符。如:

var book = {}
Object.defineProperties(book, {
  _year: {
    value: 2016,
    writable: true
  },
  edition: {
    value: 1,
    writable: true
  },
  year: {
    get: function () {
      return this._year
    },
    set: function (value) {
      this._year = value
      this.edition += 1
    }
  }
})
// 支持 Object.defineProperties() 的浏览器 IE 9+,Firefox 4+, Safari 5+, Opera 12+, Chrome
6. Object.getOwnPropertyDescriptor() 可以取得指定属性的描述符。接受两个参数,属性所在对象,属性名称。

只能取得实例属性的描述符,要取得原型对象的描述符,要在原型对象上调用这个方法。
如上例中的 book :

Object.getOwnPropertyDescriptor(book, "_year") // {configurable: false, enumerable: false, writable: true, value: 2016}
var rel = Object.getOwnPropertyDescriptor(book, "year")
console.log(rel)
// {
//   configurable: false,
//   enumerable: false,
//   get: function () {
  //   return this._year
  // },
  // set: function (value) {
  //   this._year = value
  //   this.edition += 1
  // }
// }
typeof rel.get // "function"
// 支持 Object.getOwnPropertyDescriptor() 的浏览器 IE 9+,Firefox 4+, Safari 5+, Opera 12+, Chrome
7. 关于 OO
function Person (name, age) {
  this.name = name
  this.age = age
  this.sayName = function () {
    console.log(this.name)
  }
}
var ming = new Person("ming", 13)

Person.prototype.constructor === Person // true
ming.constructor === Person // true
Person.constructor === Function // true
Function.constructor === Function // true
Function instanceof Function // true
Function instanceof Object // true

Person.prototype.sayHello = function () {
  console.log("hello")
}
ming.sayHello() // "hello"
ming.__proto__.constructor === Person // true
ming.__proto__ === Person.prototype // true
8. 构造函数

构造函数与其它函数唯一的区别在于调用方式的不同,不存在定义构造函数的特殊语法。如果不通过 new 操作符来调用,那它跟普通函数没有区别。如上面的例子:

var li = new Person("li", 15)
li.sayName() // "li"

Person("yang", 18)
window.sayName() // "yang"

var o = {}
Person.call(o, "wang", 20)
o.sayName() // "wang"
9. 原型模式

我们创建的每个函数都有一个 prototype(原型) 属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含所有实例共享的属性和方法。如:

function Person (name, age) {
  this.name = name
  this.age = age
  this.sayName = function () {
    console.log(this.name)
  }
}
Person.prototype.sayHello = function () { console.log("hello") }
var ming = new Person("ming", 12)
var li = new Person("li", 15)
ming.sayHello === li.sayHello // true
ming.sayHello === Person.prototype.sayHello // true

可以通过 isPrototypeOf() 方法来确定对象直接是否存在 原型-实例 关系,如:

Person.prototype.isPrototypeOf(ming) // true

es5 新增方法 Object.getPrototypeOf() 这个方法返回实例的 proto 即实例的构造函数的原型的值,如:

Object.getPrototypeOf(ming) === Person.prototype
// 支持 Object.getPrototypeOf() 的浏览器 IE 9+,Firefox 3.5+, Safari 5+, Opera 12+, Chrome
10. hasOwnProperty() 方法可以检测一个属性是存在于实例中,还是原型中。这个方法只在属性存在于实例中时才返回 true 。in 操作符多带带使用,只要能够通过该对象访问给定属性就返回 true, 如上例:
ming.hasOwnProperty("sayHello") // false
"sayHello" in ming // true
ming.hasOwnProperty("sayName") // true
"sayName" in ming // true

ming.sayHello = function () {
  console.log("hello in self")
}
ming.hasOwnProperty("sayHello") // true
"sayHello" in ming // true
delete ming.sayHello
ming.hasOwnProperty("sayHello") // false
"sayHello" in ming // true

ming.hasOwnProperty("sayHello1") // false
"sayHello1" in ming // false

即使将实例属性设置为 undefined / null , hasOwnProperty() in 这两个方法仍然返回 true

function hasPrototypeProperty (object, name) {
  return !object.hasOwnProperty(name) && name in object
}

for-in 循环返回的是所有能够通过对象访问的、可枚举的(enumerable: true)属性,既包括实例中的属性又包括原型中的属性。

11. es5 的 Object.keys() 方法,接受一个对象作为参数,返回实例上所有可枚举属性的字符串组成的数组。如:
var Person = function () {}
Person.prototype.sayHello = function () {
  console.log("hello")
}
var ming = new Person()
ming.name = ming
Object.keys(ming) // ["name"]

Object.getOwnPropertyNames() 方法可以得到所有实例属性,包括不可枚举的。
// 支持 Object.keys() 和 Object.getOwnPropertyNames() 的浏览器 IE 9+,Firefox 4+, Safari 5+, Opera 12+, Chrome

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

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

相关文章

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

    摘要:如果重设构造函数的原型对象,那么,会切断新的原型对象和任何之前已经存在的构造函数实例之间的联系,它们引用的仍然是最初的原型。说明返回的对象与构造函数或者与构造函数的原型属性没有关系。 说明: 此摘要笔记系列是我最近看《JavaScript高级程序设计(第3版)》随手所记。里面分条列举了一些我认为重要的、需要记下的、对我有帮助的点,是按照我看的顺序来的。摘要笔记本身没有系统性,没有全面性...

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

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

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

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

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

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

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

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

    zr_hebo 评论0 收藏0

发表评论

0条评论

roland_reed

|高级讲师

TA的文章

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