主要弄清楚这几个概念:
- 继承(原型、原型链、prototype、proto、new)
- instanceof 和 isprototypeof的区别
1. 概念
1.1 javascript 继承的来源
总是记不住javascript的prototype继承原理和原因,脑子容易混沌。查看阮一峰的文章后,自己总结如下:
- 刚开始需要一个脚本语言,不需要复杂。
- 当时java很流行,java使用了object对象。于是决定使用object对象。
- c++和java都有new来创建对象,javascript也引用了new,
- 但是简化了new,javascript中new的对象是构造函数,也就是一个函数。
- 但是new有一个缺点就是无法共享数据,于是prototype出来了,这样私有数据在构造函数中,共享数据在prototype中。
function dog(name){
this.name = name
}
dog.prototype = {
type:"animate"
}
var a = new dog('gou')
var b = new dog('mao')
dog.prototype.type = 'dongwu';
console.log(a.name); // gou
console.log(b.name); // mao
console.log(a.type); // dongwu
console.log(b.type); // dongwu
1.2 原型链概念
少不得要放这张图片(^_^)
下面是我理解的概念:原概念可以看这里
- 实例对象有__proto__属性(指向构造函数的原型对象)
- 函数有prototype属性
- 函数的prototype是对象类型
- __proto__属性指向函数的原型对象,prototype就是函数的原型对象
- Object.__proto__ === Function.__proto__ === foo.__proto__ === Function.prototype
我理解的原型链:
javascript一切皆对象,每个实例对象都有__proto__属性,指向它构造函数的实例对象(prototype),而实例对象又是一个对象,所以又拥有了__proto__属性,直到null为止,这就是原型链的生成。
ps:为什么使用__proto_属性,可以参考本文下方的new的实现。_
光概念不行,还要有两个栗子:
Function.prototype.a = 'Function'
Object.prototype.a = 'Object'
function foo(name){
}
var a = new foo();
console.log(a.a) // Object
// 原型链从__proto__开始查找,
// 步骤:foo.__proto__ ---> foo.prototype ---> Object.prototype
// 结果: Object, 根本未经历Function.prototype
function foo(){
}
var a = new foo();
console.log(a.__proto__ === foo.prototype); // true, proto指向声明它的原型的prototype
console.log(foo.__proto__ === Function.prototype) // true, function声明变量的proto指向Function.prototype
console.log(Function.prototype.__proto__ === Object.prototype); // true, prototype也有proto,指向Object的prototype
console.log(Object.prototype.__proto__ === null); //true, Object的prototype的proto指向null
ps:最好去权威的网站看一些原始的概念,这样会更好。
3.instanceof
A instanceof B
说法1:B 构造函数的prototype对象是否在A的原型链上
说法2:A对象是否是B对象的实例
说法3:B对象是否是A对象的父对象
我觉得说法2还是最合适的
伪代码:
function instanceof(left,right){
while(true){
if(left.__proto__ === null){
return false;
}
if(left.__proto__ === right.prototype){
return true;
}
left = left.__proto__;
}
}
易错小栗子:
var simpleStr = "This is a simple string";
var myString = new String();
var newStr = new String("String created with constructor");
simpleStr instanceof String; // 返回 false, 检查原型链会找到 undefined
myString instanceof String; // 返回 true
newStr instanceof String; // 返回 true
myString instanceof Object; // 返回 true
Object.create(null) instanceof Object // false, 创建了一个原型为null的空对象,检查原型链会找到 undefined
易错小栗子二:和isprototypeof的区别(答案全部是true)
var fn = function(){
this.nick = 'nick'
this.age = '18'
}
fn.prototype.getNick = function(){
console.log(this.nick)
}
fn.hello = function(){
console.log('hello')
}
fn.getAge = function(){
console.log(this.hello())
return '1'
}
var sub = function(){
}
sub.prototype = Object.create(fn.prototype)
sub.prototype.constructor = sub;
var sb = new sub();
console.log(sb instanceof fn)
console.log(fn.prototype.isPrototypeOf(sb))
var c = Object.create(fn.prototype)
console.log(c instanceof fn)
console.log(fn.prototype.isPrototypeOf(c))
var obj = {
a:'a'
}
var t = Object.create(obj)
console.log(t instanceof Object)
console.log(Object.prototype.isPrototypeOf(t))
4. isprototypeof
A.isPrototypeOf(B):
B对象是否在A的原型链上
var o={
};
function Person(){
};
var p1 =new Person();//继承自原来的原型,但是现在已经无法访问
Person.prototype=o;
var p2 =new Person();//继承自o
console.log(o.isPrototypeOf(p1));//false o不是p1的原型
console.log(o.isPrototypeOf(p2));//true o是p2的原型
// 这个栗子来源于网上,我稍微修改了一下。我认为这个栗子并不好,
// 因为实际使用一般是o.prototype.isPrototypeOf(p2),而非o.isPrototypeOf(p2)
5. instanceof和isprototypeof的区别
我认为就是参数的区别
不是参数的区别,是后者检测的更全面(可以对constructor检测)
就是参数的区别
object instanceof constrouctor
prototypeObject.isPrototypeOf(Object)
6. new
引用自:地址
function myNew(){
var constructor = [].shift.call(arguments); //注意是shift,不是slice
var obj = new Object();
obj.__proto__ = constructor.prototype;
constructor.apply(obj,arugments)
return obj;
}