js的继承方式
/**
* 经典的js寄生组合式继承
*/
function MyDate() {
Date.apply(this, arguments);
this.abc = 1;
}
function inherits(subClass, superClass) {
function Inner() {}
Inner.prototype = superClass.prototype;
subClass.prototype = new Inner();
subClass.prototype.constructor = subClass;
}
inherits(MyDate, Date);
MyDate.prototype.getTest = function() {
return this.getTime();
};
let date = new MyDate();
console.log(date.getTest());
Date作为构造函数来实例化
new Date();
new Date(value);
new Date(dateString);
new Date(year,month,day,hours,minutes,seconds,milliseconds);
ES5黑魔法
// 需要考虑polyfill情况
Object.setPrototypeOf = Object.setPrototypeOf ||
function(obj, proto) {
obj.__proto__ = proto;
return obj;
};
/**
* 实际上返回的是Date对象
*/
function MyDate() {
// bind属于Function.prototype,接收的参数是:object, param1, params2...
var dateInst = new(Function.prototype.bind.apply(Date, [Date].concat(Array.prototype.slice.call(arguments))))();
// 更改原型指向,否则无法调用MyDate原型上的方法
// ES6方案中,这里就是[[prototype]]这个隐式原型对象,在没有标准以前就是__proto__
Object.setPrototypeOf(dateInst, MyDate.prototype);
dateInst.abc = 1;
return dateInst;
}
// 原型重新指回Date,否则根本无法算是继承
Object.setPrototypeOf(MyDate.prototype, Date.prototype);
MyDate.prototype.getTest = function getTest() {
return this.getTime();
};
let date = new MyDate();
// 正常输出,譬如1515638988725
console.log(date.getTest());
shim:是一个库,它将一个新的API引入到一个旧的环境中,而且仅靠旧环境中已有的手段实现
polyfill:就是一个用在浏览器API上的shim,主要抚平不同浏览器之间对js实现的差异
先检查当前浏览器是否支持某个API,如果不支持的话就加载对应的polyfill.然后新旧浏览器就都可以使用这个API了
prototype 属性:向对象添加属性
ES6大法
class MyDate extends Date {
constructor() {
super();
this.abc = 1;
}
getTest() {
return this.getTime();
}
}
let date = new MyDate();
// 正常输出,譬如1515638988725
console.log(date.getTest());
ES6写法,然后Babel打包(无法正常调用的)
因为转译后的ES5源码中,仍然是通过MyDate
来构造,
而MyDate
的构造中又无法修改属于Date
内部的[[Class]]
之类的私有标志,
因此构造出的对象仍然不允许调用Date
方法(调用时,被引擎底层代码识别为[[Class]]
标志不符合,不允许调用,抛出错误)
以上的方法的差别:
- MyDate们的__proto__指向不一样
- Object.prototype.toString.call的输出不一样
- 对象本质不一样,可以正常调用的
1, 3
都是Date
构造出的,而其它的则是MyDate
构造出的
普通对象是没有prototype属性的,只有隐藏属性__proto__,函数对象则两者兼有
所有函数对象的原型对象都继承自原始对象,即fn.prototype.__proto__为原始对象,Object函数,他的原型对象就是原始对象,即Object.prototype。
什么是原型链回溯?
用 new方法初始化函数得到新对象的__proto__属性指向原型对象
function f(){};
var a = new f();
a.__proto__=>f.prototype.__proto__=>Object.prototype=>null
把有__proto__串起来的直到Object.prototype.__proto__为null的链叫做原型链。原型链实际上就是js中数据继承的继承链。