You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionParent(){this.value=1}Parent.prototype.method=function(){console.log('value: '+this.value)}functionChild(){// this -> new Child()Parent.call(this);// 调用Parent构造函数}varc1=newChild();console.log(c1.value);// 1c1.method();// 报错:Uncaught TypeError: c1.method is not a functionChild.prototype=Parent.prototype;//继承父方法varc2=newChild();c2.method();// 'value: 1'
我们经常可以用到的字符串函数
substr
、replace
、indexOf
等,是因为 String 对象上的 prototype 预先定义了这些方法。str
为String
的一个实例。JavaScript标准库中常用的内置对象上 prototype 的方法还有:
Array.prototype.push
、Array.prototype.push
Date.prototype.getDate
、Date.prototype.getYear
Function.prototype.toString
、Function.prototype.call
...
我们使用构造函数创建一个对象:
在这个例子中,
User
是一个构造函数,我们使用new
创建了一个实例对象 userprototype
JavaScript 不包含传统的类继承模型,而是使用 prototype 原型模型。
每个函数都有一个 prototype 属性,换句话说, prototype 是函数才会有的属性
函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的 实例 的原型。也就是说这个例子中 User 的属性 prototype 对象是 user1 和 user2 的原型。
既然函数的 prototype 属性指向了一个对象,我们可以重写原型对象
这样,我们就可以 new User 对象以后,就可以调用 greeting 方法了。
然而将原子类型赋给 prototype 的操作将会被忽略
我们还可以在赋值原型 prototype 的时候使用 function 立即执行的表达式来赋值:
它的好处就是可以封装私有的 function,通过 return 的形式暴露出简单的使用名称,以达到public/private的效果。
上述使用原型的时候,都是直接赋值原型对象,这样会覆盖之前已定义好的原型,导致之前原型上的方法或属性丢失,所以通常分开设置/覆盖 一个已知函数的 prototype
_proto_
所有 JavaScript 对象(null除外)都有的一个
__proto__
属性,这个属性指向该对象的原型不管你创建多少个 User 对象实例,他们的原型指向的都是同一个 User.prototype
注: _proto_ 并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,不建议在生产中使用该属性,我们可以使用ES5的方法 Object.getPrototypeOf 方法来获取实例对象的原型。
当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止。
到查找到达原型链的顶部 - 也就是 Object.prototype - 但是仍然没有找到指定的属性,就会返回 undefined。
如果一个属性在原型链的上端,则对于查找时间将带来不利影响。特别的,试图获取一个不存在的属性将会遍历整个原型链。
并且,当使用 for in 循环遍历对象的属性时,原型链上的所有属性都将被访问。
所以在使用 for in loop 遍历对象时,推荐总是使用 hasOwnProperty 方法, 这将会避免原型对象扩展带来的干扰。
构造函数
通过 new 关键字方式调用的函数都被认为是构造函数
原型 constructor 属性指向构造函数,在构造函数内部,this 指向新创建的对象 Object
如果被调用的函数没有显式的 return 表达式,则隐式的会返回 this 对象 - 也就是新创建的对象。
显式的 return 表达式将会影响返回结果,但总是会返回的是一个对象。
这里得到的 foo 是函数返回的对象,而不是通过new关键字新创建的对象。new Foo() 并不会改变返回的对象 foo 的原型, 也就是返回的对象 foo 的原型不会指向 Foo.prototype 。 因为构造函数的原型会被指向到新创建的对象,而这里的 Foo 没有把这个新创建的对象返回,而是返回了一个包含 b 属性的自定义对象。
如果 new 被遗漏了,则函数不会返回新创建的对象。
为了不使用 new 关键字,经常会使用工厂模式创建一个对象。
上面的方式看起来出错,并且可以使用闭包来达到封装私有变量, 但是随之而来的是一些不好的地方。
继承
下面通过 call 实现继承,并将父级 prototype 给子 prototype
但是这样继承存在一个问题,接上面代码继续
因为 Parent.prototype === Child.prototype,原型是同一个引用,可以直接将子类prototype 与 父类分离
The text was updated successfully, but these errors were encountered: