系列文章:算法
在 JavaScript 中,共有6种类型主要类型:数组
对象的内容是由一些存储在特定命名位置(任意类型的)值组成的,咱们称之为属性。浏览器
⚠️注意:即便在对象的文字形式中声明一个函数表达式,这个函数都不会“属于”一个对象,他们只是对于相同函数的多个引用。bash
从 ES5 开始,全部的属性都具有属性描述符:闭包
writable:是否能够修改属性的值。值为false时,至关于定义了一个空操做setter。函数
configurable:若是属性是可配置的,就可使用 defineProperty(...) 进行修改属性描述符。configurable的值设置为false是单向操做,没法撤销!post
⚠️注意:即便 configurable:false,仍是能够把 writable 的值从 true 改为 false,但不能够由 false 改为 true。测试
enumerable:控制的是属性是否会出如今对象的属性枚举中。ui
⚠️注意:属性不必定包含值——也多是包含getter/setter的“访问描述符”this
属性访问时,对象默认的内置 [[Get]] 操做首先在对象中查找是否有名称相同的属性,遍历可能存在的[[prototype]]链,若是不管如何也没找到名称相同的属性,则返回值 undefined。
⚠️注意:访问变量时,没找到会抛出一个 ReferenceError 异常。刚问对象属性时,没找到会返回 undefined。
当给属性赋值:
JavaScript 中的对象有一个特殊的 [[prototype]] 内置属性,是对其余对象的引用。全部普通的 [[prototype]] 最终都会指向内置的 Object.prototype。
全部的函数默认都会拥有一个名为 prototype 的公有且不可枚举的属性,它会指向另外一个对象,这个对象被称为原型,这个对象默认有一个公有且不可枚举的属性.constructor,这个属性引用的是对象关联的函数。
[[prototype]]机制就是指对象中的一个内部连接引用另外一个对象。
JavaScript 会在两个对象之间建立一个关联,这样一个对象就能够经过委托来访问另外一个对象的属性和函数。
var bar = Object.create(foo);
会建立一个对象 bar 并把它关联到 foo。
调用 Object.create(...)会凭空建立一个“新”对象,并把新对象内部的[[prototype]] 关联到指定的对象...,这样会直接把原始的关联对象抛弃掉。
有如下几种方法检查两个对象之间的关系:
⚠️注意:绝大多数(不是全部)的浏览器支持__proto__ 这个非标准的方法访问内部的[[prototype]],__proto__存在于内置 Object.prototype 中,看起来像个属性,其实更像一个 getter/setter。
练习题1:
function Test() {
Test.prototype.add = num => {
this.number = num
}
Test.prototype.number = 0
}
t1 = new Test()
t2 = new Test()
t1.add(12)
var a = t1.number
var b = t2.number
console.log(a, b) // => 0,12
复制代码
每实例化一次Test,Test.prototype.add都会被从新赋值一次,而且赋值的函数为箭头函数,箭头函数无自身的上下文,其中的this指向Test上下文中的this,即每次实例化的实例对象。因此,t2 实例化后 Test.prototype.add 里的 this 指向t2,t1 调用 add 函数时,给 t2 的number 赋值。
练习题2:
var A = function() {};
A.prototype.n = 1;
var b = new A();
A.prototype = {
n: 2,
m: 3
}
var c = new A();
console.log(b.n); // 1
console.log(b.m); // undefined
console.log(c.n); // 2
console.log(c.m); // 3
复制代码
⚠️注意:JavaScript 中的引用和其余语言中的引用/指针不一样,不能指向别的变量或者引用,只能指向值。
b 在实例化过程当中,b.__proto__ = A.prototype
,此时 A.prototype = {n: 1}
,当 A.prototype = { n: 2, m: 3 }
时,打破原型链,A.prototype 引用了新内存地址的对象,b.__proto__
指向的依旧是旧内存地址的对象。若是是 A.prototype.n = 2; A.prototype.m = 3;
就不会指向新的引用。
练习题3:
var F = function() {};
Object.prototype.a = function() {
console.log('a');
};
Function.prototype.b = function() {
console.log('b');
}
var f = new F();
f.a(); // a
f.b(); // TypeError: f.b is not a function
F.a(); // a
F.b(); // b
复制代码
f的原型链:f => f.__proto__ => F.prototype => F.prototype.__proto__ => Object.prototype => Object.prototype.__proto__ => null
F的原型链:F => F.__proto__ => Function.prototype => Function.prototype.__proto__ => Object.prototype => Object.prototype.__proto__ => null
练习题4:
function Person(name) {
this.name = name
}
let p = new Person('Tom');
question1: p.__proto__等于什么? // p.__proto__ === Person.prototype
question2: Person.__proto__等于什么? // Person.__proto__ === Function.prototype
复制代码
以为有收获的,点个赞再走吧~