function f1(){};
var f2 = function();
var f3 = new Function('args','alert(args)');
// 函数对象 f1,f2,f3
var c1 = {};
var c2 = new Object();
var c3 = new function(){};
// 普通对象 c1,c2,c3
凡是通过new Function()创建的对象都是函数对象,其他的都是普通对象。Function Object 也都是通过 New Function()创建的所以它们也是函数对象
注意:尽管可以使用 Function 构造函数创建函数,但最好不要使用它,因为用它定义函数比用传统方式要慢得多。不过,所有函数都应看作 Function 类的实例。
function Foo(name) {
this.name = name;
this.arr = [1, 2];
}
Foo.prototype.sayName = function () {
console.log(this.name);
}
function Bar(name) {
Foo.call(this, name); // 第二次调用
}
Bar.prototype = new Foo(); // 第一次调用
Bar.prototype.constructor = Bar;
var s1 = new Bar('zhangsan');
var s2 = new Bar('lisi');
console.log(s1.arr); // [1, 2]
s1.arr.push(3);
console.log(s1.arr); // [1, 2, 3]
console.log(s2.arr); // [1, 2]
s1.sayName(); // zhangsan
s2.sayName(); // lisi
缺点:
调用了两次父类的构造函数
原型式继承
思想:借助原型,可以基于已有的对象创建新对象
function object(o) {
function F() {};
F.prototype = o;
return new F();
}
var obj = {
name: 'lili'
};
var p = object(obj)
console.log(p.name)
//这样 p 对象就可以拿到 obj 的属性了
ES5新增了方法规范化了原型式继承。即: Object.create()
寄生式继承
思想:在继承对象的同时通过添加属性与方法增强这个新对象,原型式继承的加强版
function createAnother(o) {
var obj = Object.create(o); // 通过调用函数创建一个新对象
obj.sayHi = function () { // 给这个对象添加方法
console.log("hi");
}
return obj; //返回这个新对象
}
function Foo() {}
Foo.prototype.sayName = function () {
console.log(this.name);
}
var now = createAnother(Foo.prototype);
now.name = 'lili'
now.sayName(); // lili
now.sayHi(); // hi
ES6中的继承
ES6中可以声明类( class )提供了extends关键字实现类的继承,定义的类只是语法糖,目的是让我们用更简洁明了的语法创建对象及处理相关的继承。
class Foo {
constructor(name) {
this.name = name
}
sayName() {
console.log(this.name)
}
}
class Bar extends Foo {
constructor(name, age) {
super(name); // 调用父类的constructor(x)
this.age = age
}
sayHi() {
console.log('Hi my name is ');
super.sayName();
}
}
var s1 = new Bar('lili', 18);
s1.sayHi();
class Bar extends null {}
Bar.__proto__ === Function.prototype // true
Bar.prototype.__proto__ === undefined // true
Bar是一个普通函数, 所以直接继承 Funciton.prototype 但是 Bar 调用后返回的对象不继承任何方法, 所以它的 __proto__ 指向Function.prototype, 即实质上执行了下面的代码:
class Bar extends null {
constructor() {
return Object.create(null);
}
}
Object.getPrototypeOf方法可以用来从子类上获取父类。
Object.getPrototypeOf(Bar)===Foo //true
实例的 __proto__ 属性
class Foo {
}
class Bar extends Foo {
}
var p1=new Foo();
var p2=new Bar();
console.log(p2.__proto__ === Bar.prototype); //true
console.log(Bar.prototype.__proto__===Foo.prototype); //true
console.log(p2.__proto__.__proto__===p1.__proto__); //true