JavaScript学习03-原型链

详解链接:https://www.jianshu.com/p/dee9f8b14771

原型链

//原型链
const obj = new Object();
const obj2 = {

};
//每个对象都有一个—__proto__属性
obj2.__proto__.name = 'guo';
console.log(obj2.name);

function Fun() {

}
//每个function都有一个prototype属性
//当我们创建一个函数对象时,它的__proto__和所属类构造函数本身的prototype指向同一个对象
Fun.prototype.name = 'guoyunhao';
const f = new Fun();

console.log(f.__proto__ === Fun.prototype);
//先找本身有没有name属性,如果找不到,会按顺序往上在原型链上找 
//obj.__proto__.__proto__.name 直到Object.prototype为止
console.log(f.name);

Object.prototype.name = "根类名字";
var o1 = new Object();
var o2 = {};
console.log(o1.name);
console.log(o2.name);

var o3 = {
    name: '自己的名字'
};
o3.__proto__.name = "o3proto的名字";

console.log(o3.name);
//delete删除对象的属性,不能删除对象本身
delete o3.name;
console.log(o3.name);

//因为__proto__已被废弃,要使用如下方法设置prototype
var o3P = {
    age: 22
};
Object.setPrototypeOf(o3, o3P);
console.log(o3.age);

通过原型链创建类

//new User();
//通过原型链创建所谓的类
function User() { //在调用new User()时候,因为new关键字使其内部机制执行如下 //如果不加new,它会像普通函数一样执行 /* var thisobj = {}; thisboj.__proto__ = User.prototype; return thisobj; */ //私有属性 var name = 'guo'; //特权方法 因为能访问私有属性,所以叫特权方法 this.print_name = function() { console.log(name); }; } //原型属性 User.prototype.fn = function() { console.log('fn'); }; User.prototype.type = '类的类型'; var u = new User(); u.print_name(); //u.__proto__.fn u.fn(); //静态属性 User.version = 1.0; User.staticFunc = function() {}; //调用静态方法和属性 var version = User.version; var staticFunc = User.staticFunc;

继承

//继承
function People(name = 'default') {
    this.name = name;
    this.changeName = function(name) {
        this.name = name;
    };
}
People.prototype.fnP = function() {
    console.log("people fnP");
};
People.staticFunc = function() {
    console.log('static People func');
}

function User(name) {}
User.prototype.fnU = function() {};

//原型链实现继承
User.prototype.__proto__ = People.prototype;
//User.prototype = new People(); 这样不行,原因在下面截图处

var u = new User(); //Object.setPrototypeOf(u, new People()); //u.changeName('guo'); u.fnP(); //call apply实现继承 function Guo(name) { //特权属性的继承 People.call(this, name); this.height = 187; } //这里是整个函数对象的__proto__指向了People函数对象,所以可以继承静态方法 Guo.__proto__ = People; //而这里Guo.prototype是Guo的原型对象,是Guo构造函数创建的一个普通对象,相当于实例才能用People中的方法 //Guo.prototype = People; var g = new Guo("guoyunhao"); //g.__proto__ = People; g.changeName("eric"); console.log(g.name); //g.staticFunc(); Guo.staticFunc();
var obj = {};
console.log(obj.name);
Object.prototype.name = 'guo';
console.log(obj.name);
console.log(obj.__proto__ === Object.prototype);


//构造函数
function User() {

}
//有了原型链这一机制,创建无数个User实例对象,只需要一份changeAge方法,节省内存空间
User.prototype.age = 23;
User.prototype.changeAge = function(age) {
    //这里的this是User.prototype
    this.age = age;
}
var u = new User();
var u2 = new User();
u.age = 16;
u.changeAge(17);
console.log(u.age);
console.log(u2.age);
//不节省内存的方式
//这样写的话每次new出来一个User2对象都要执行函数内部的所有属性和方法
function User2() {
    this.age = 23;
    this.changeAge = function(age) {
        this.age = age;
    };
}

function People(name = 'default') {
    this.name = name;
    // this.changeName = function(name) {
    //     this.name = name;
    // };

}
People.prototype.changeName = function(name) {
    this.name = name;
};

function Guo(name, age) {
    //继承特权属性
    People.call(this, name);
    this.age = age;
}
Guo.prototype.__proto__ = People.prototype;
g = new Guo('guodage', 23);
g.changeName('guoyunhao');
console.log(g.name);

深入理解

//每个对象都有 __proto__ 属性,但只有函数对象才有 prototype 属性
//凡是通过new Funtion()产生的对象都是函数对象
function f1() {};
var obj = new f1();
console.log(typeof f1, typeof obj);
//原型对象就是一个普通对象,除了Function.prototype,它是函数对象,因为它是new Function()创建出来的,但它没有prototype属性
console.log(Function.prototype.__proto__ === Object.prototype);
console.log(Object.prototype.__proto__);
console.log(typeof f1.prototype);
console.log(f1.prototype.constructor === f1);
console.log(obj.constructor === f1);
//普通对象没有prototype属性
console.log(f1.prototype.prototype);
//原型对象(Person.prototype)是 构造函数(Person)的一个实例。

实现继承的错误用法与错误原因

posted @ 2018-07-17 15:37  Eric云皓  阅读(80)  评论(0)    收藏  举报