Open rccoder opened 8 years ago
如果之间学习过cpp 、java 之类的语言,都会知道他们是可以基于类 class 进行继承的, 在早期 JavaScript 中,并没有类继承这个概念,要实现JavaScript 中的继承,需要原型来帮助。
cpp
java
class
JavaScript
比如在下面的这段代码中:
function Foo () { this.value = 1; }; Foo.prototype = { method: function () {}; }; //设置Bar的原型为Foo()的实例 Bar.prototype = new Foo(); Bar.prototype.foo = 'Hello World'; //修正Bar的constructor Bar.prototype.constructor = Bar; //创建一个Bar的实例 var test = new Bar();
在这段代码中,就一直维护着一个原型链,抽象化的理解起来可能是这样的:
test [Bar的实例] Bar.prototype [Foo的实例] {foo: 'Hello World!'} Foo.prototype {method: function(){}} Object.prototype {...}
很好去理解,test 是从Bar.prototype 和 Foo.prototype 中继承下来的,所以他能够访问Foo 实例属性中的value 。
Bar.prototype
Foo.prototype
Foo
value
需要注意的是,在 new Bar 操作中,并不会重新创建一个Foo 的实例,而是会重复的使用在他的原型上的那个实例。
new Bar
除此之外,原型是共享的,如果我们有Foo.prototype = Bar.prototype 的写法,改变这两个对象任何一个的原型都会影响另外一个,这在大多的情况下是不可取的。
Foo.prototype = Bar.prototype
当对象查找一个属性的时候,他会沿着原型链一直往上追踪,直到直到为之。当然 Object.prototypr 就是这个链的最后一层了,如果还是没找到,就会返回undefined 。
Object.prototypr
undefined
在性能方面,原则上应该尽量避免原型链太长。正如用for ... in ... 去遍历的时候,他会去遍历整个原型链,这往往在比较高的性能要求或者普通的遍历中是不可取的。
for ... in ...
为了去判断一个对象包含的属性是他本身就有的还是在原型链上的,需要使用继承在Object prototype 上的hasOwnProperty 方法。
Object prototype
hasOwnProperty
比如在下面的例子中
Oboject.prototype.bar = 1; var foo = { value: 2; }; foo.var //通过原型链继承自Object,输出1 'bar' in foo; //通过整个原型链进行查找,输出true foo.hasOwnProperty('bar'); //false foo.hasOwnProperty('value') //true
在for ... in ... 的遍历中,一般建议使用hasOwnProperty 的方法。
需要注意的是: javascript并没有对hasOwnProperty 做相关的保护,如果恰巧对象有这个叫做hasOwnProperty 的属性,那么产生的结果应该不是我们所期待的。比如像下面这样:
javascript
var foo = { hasOwnProperty: function () { return flase}; bar: '1'; }; foo.hasOwnProperty('bar') //正如你猜的那样,返回的值永远是false
这时候可能需要做的就是调用外部的hasOwnproperty, 对,就是用call 或者apply。像下面这样:
hasOwnproperty
call
apply
//返回true Object.hasOwnProperty.call(foo, 'bar'); Object.hasOwnProperty.apply(foo, ['bar']);
Object.getOwnPropertyNames()
@holynewbie :+1:
ES2015 中的好特性!http://www.ecma-international.org/ecma-262/6.0/#sec-object.getownpropertynames
还可以使用这个Object.keys
简介
如果之间学习过
cpp
、java
之类的语言,都会知道他们是可以基于类class
进行继承的, 在早期JavaScript
中,并没有类继承这个概念,要实现JavaScript
中的继承,需要原型来帮助。比如在下面的这段代码中:
在这段代码中,就一直维护着一个原型链,抽象化的理解起来可能是这样的:
很好去理解,test 是从
Bar.prototype
和Foo.prototype
中继承下来的,所以他能够访问Foo
实例属性中的value
。需要注意的是,在
new Bar
操作中,并不会重新创建一个Foo
的实例,而是会重复的使用在他的原型上的那个实例。除此之外,原型是共享的,如果我们有
Foo.prototype = Bar.prototype
的写法,改变这两个对象任何一个的原型都会影响另外一个,这在大多的情况下是不可取的。当对象查找一个属性的时候,他会沿着原型链一直往上追踪,直到直到为之。当然
Object.prototypr
就是这个链的最后一层了,如果还是没找到,就会返回undefined
。hasOwnProperty
在性能方面,原则上应该尽量避免原型链太长。正如用
for ... in ...
去遍历的时候,他会去遍历整个原型链,这往往在比较高的性能要求或者普通的遍历中是不可取的。为了去判断一个对象包含的属性是他本身就有的还是在原型链上的,需要使用继承在
Object prototype
上的hasOwnProperty
方法。比如在下面的例子中
在
for ... in ...
的遍历中,一般建议使用hasOwnProperty
的方法。需要注意的是:
javascript
并没有对hasOwnProperty
做相关的保护,如果恰巧对象有这个叫做hasOwnProperty
的属性,那么产生的结果应该不是我们所期待的。比如像下面这样:这时候可能需要做的就是调用外部的
hasOwnproperty
, 对,就是用call
或者apply
。像下面这样: