一:先来几个干货
1 ,变量先声明后使用,使用未声明的变量会报错(大多程序语言使用未声明的变量都会报错,JS非严格模式使用未声明的变量,则会变成全局变量,严格(strict)模式也会报错)。2,无(null)生万物,一切皆对象。(自然规律,JS貌似也遵守了,(js里的)null可以理解为指针对象是内存的一块区域,用于存储是对象)。
3,对象分为可执行对象(即函数对象)与不可执行对象(普通对象),对象拥有属性(特征)、方法(行为)。
4,对象的特殊属性:原型(prototype)、构造函数(constructor)、构造函数原型(__proto__,__proto__是constructor.prototype的简写)。
5,一切对象都有__proto__属性(null例外);只有函数对象有prototype属性。
6,程序语言的继承分为类继承和原型继承,JS的继承属于原型继承(此处所说的原型是__proto__不是prototype)。
二:再来一张图
三:有图有干货开始干活了(均在谷歌浏览器下测试)
约定:
(1)下文说的
XX的原型
都是通过
构造函数原型进行访问(constructor.prototype简写__proto__各大浏览器也是默认内置实现)。
(2)对象原型是指Object构造函数原型:Object.prototype//({}.__proto__)===Object.prototype=>true;
数组原型是指Array构造函数原型:Array.prototype//Array.prototype===[].__protto=>true;
其他类型原型类同。
1、Object.ptototype(对象类型函数原型简称对象原型,下文同)是什么鬼。来个图看一下:
代码如下:
Object.prototype//对象类型函数原型
运行如下
2、看图验干货:
1,对象原型的原型是null;(无声万物);
代码如下
Object.prototype.__proto__===null;//返回true,注意和Object.__proto的区别,自己可以可以看图猜测下。
运行如下
2,对象分为可执行对象、不可执行对象(一切皆对象);
代码如下
Math.__proto__===Object.prototype//true
JSON.__proto__===Object.prototype//true
({}).__proto__===Object.prototype//true
Function.prototype.__proto__===Object.prototype//true;
运行如下:
3,原型细分,类型原型产生(万物苏生ing.......);
代码如下
Boolean.__proto__===Function.__proto__//true
Number.__proto__===Function.__proto__//true
String.__proto__===Function.__proto__//true
Array.__proto__===Function.__proto__//true
Object.__proto__===Function.__proto__//true
Date.__proto__===Function.__proto__//true
RegExp.__proto__===Function.__proto__//true
Error.__proto__===Function.__proto__//true
Map.__proto__===Function.__proto__//true es6的类型
Set.__proto__===Function.__proto__//true es6的类型
Promise.__proto__===Function.__proto__//true es6的类型
运行如下
4,错误原型再细分细分,错误开始分类(什么错都是错.......);
代码如下:
EvalError.__proto__===Error//true
SyntaxError.__proto__===Error//true
TypeError.__proto__===Error//true
RangeError.__proto__===Error//true
URIError.__proto__===Error//true
ReferenceError.__proto__===Error//true
运行如下
5,看完原型链开始看看它的继承吧(继承:你有的我都想有);
1,继承的来源:prototype or __proto__(constructor.prototype);
代码如下:
//使数组都有pp方法;随即验证下prototype与__proto__属性
Array.pp=function(){
console.info('prototye');
};
Array.prototype.pp=function(){
console.info('__proto__');
}
[].pp()//->console.info('__proto__');
[].prototype//->undefined;
[].__prototype//->看下图
运行如下:
6,熟悉完了prototype、__proto__看看constructor
对象的consructor属性很简单就是指向其构建函数,愉快的举个栗子。
({}).constructor===Object//true;
({}).constructor.constructor===Function//true;
({}).constructor.constructor.constructor===Function//构造函数到Function是到尽头了,再怎么constructor都是Function本身
7,学以致用,举栗子看继承(坚持:我是最后一个:);
function Parent(start) {
this.name = 'parent的属性name';
this.start = start;
}
Parent.prototype.do = function() {
console.info('do-parent:');
};
Parent.prototype.say = function() {
console.info('say-parent:');
};
Child.prototype.constructor = Child; //设置其构造函数。
/*使Child继承Parent的方式:**/
//<1>原型式继承:缺点是不能像起他语言那样像父类传递属性值
function Child(end) {
this.name = 'child的属性name';
this.end = end;
}
Child.prototype = new Parent(45);
Child.prototype.say = function() {
console.info('Parent+Child:' + (this.start + this.end));
};
var a = new Child(55);
a.do();
a.say();
//类式继承:缺点是每次new Child都是不同实例不能共享公有方法。
function Child(end, start) {
Parent.call(this, start);
this.name = 'child的属性name';
this.end = end;
}
Child.prototype.say = function() {
console.info('Parent+Child:' + (this.start + this.end));
};
var a = new Child(45,55);
a.do(); //=>a.do不是一个函数
a.say();
//混合式:原型式继承和类式继承一起使用。
function Child(end, start) {
Parent.call(this, start); //第二次条用,开始关注其实例属性。
this.name = 'child的属性name';
this.end = end;
}
Child.prototype = new Parent(); //第一次条用;仅仅是获取它的原型方法,对于其属性无关紧要;
Child.prototype.say = function() {
console.info('Parent+Child:' + (this.start + this.end));
};
var a = new Child(45,55);
a.do();
a.say();
//寄生式混合继承:因为混合继承的第一次条用父Parent的时候不关注其实例属性,仅仅是获取其父上的方法。
//如果Parent的构造函数足够复杂的时候会造成资源浪费,性能降低。所以可以用一个空的构造函数进行过渡。
/**es5中Object.create实现了create函数,es5中可以Object.create或者用Object.setPrototypeOf*/
var create = function(proto) {
function A() {}
A.prototype = proto;
return new A();
};
Child.prototype = Object.create(Parent.prototype)||create(Parent.prototype);
//或者直接设置其原型Object.setPrototypeOf(Child,Parent.prototype)
Child.prototype.say = function() {
console.info('Parent+Child:' + (this.start + this.end));
};
var a = new Child(55, 45);
a.do();
a.say();
//es6快捷语法类继承。
class Parent {
constructor(start) {
if (start) {
this.start = start;
}
}
}
Parent.prototype.do = function() {
console.info('parent-do');
};
class Child extends Parent {
constructor(end, start) {
super(start);
this.end = end;
}
}
Child.prototype.say = function() {
console.info('Parent+Child:' + (this.start + this.end));//属性也继承了.
};
var a=new Child(45,55)
a.do();//方法继承
a.say();
总结: