原型和原型链

其他地方都好理解,就这里,十分有意思,Object()是由Function.prototype创建,但是他由继承自object.prototype.由Object()创建。那么到底谁先谁后,鸡蛋问题。先有鸡还是先有蛋。那么答案是什么呢?

先说答案,万物皆对象不准确,应该说万物皆Function创建。不过有个内置的object.prototype.

说法1.

Function 是 built-in 的对象,也就是并不存在“Function对象由Function构造函数创建”这样显然会造成鸡生蛋蛋生鸡的问题。实际上,当你直接写一个函数时(如 function f() {} 或 x => x),也不存在调用 Function 构造器,只有在显式调用 Function 构造器时(如 new Function('x', 'return x') )才有。

先有Function
即先有 Function.prototype 然后有的 function Function() ,所以就不存在鸡生蛋蛋生鸡问题了,把  Function.__proto__ 指向 Function.prototype 是为了保证原型链的完整,让 Function 可以获取定义在 Object.prototype 上的方法。

所以JavaScript里__proto__这个东西其实是很随意的,放在哪个函数的prototype里,哪个函数就成了你爹

函数声明的三种方式

函数声明方式创建Function,语法如下:

function sum(x,y){
    return x + y;
}

函数表达式定义Function,用var 如下:

var sum = function(x,y){
    return x + y;
};

第二种方法不要忘记在结尾加上分号

另外还可以使用Function 构造函数。如:

var sum = new function("x","y","return x + y");

 

基础,构造函数,实例成员,静态成员

实例成员,构造函数内部this添加。。静态成员,对构造函数添加的属性。

构造函数可以访问静态成员而不可以访问实例成员。

实例化,let son = new Person({name:’Davia’})

-实例化一个对象过程。

1.创建空对象{}

2.绑定对象原型链 son.__proto__ = Person.prototype.

3.重新绑定this指向新对象 Person.call(this)

4.赋值 5.返回return this

-如果在构造函数上直接定义方法,实例不共享方法。通过this定义方法。

实例需要开辟新的内存空间。

-构造函数通过原型分配的函数,是所有对象共享的

原型

3.2 原型的作用是什么?
原型的作用,就是共享方法。
我们通过 Father.prototype.method 可以共享方法,不会反应开辟空间存储方法。

四、原型链
4.1 什么是原型链?
原型与原型层层相链接的过程即为原型链。

原型查找,从实例到构造函数自身,到构造函数的prototype,到Object原型的prototype。

每个构造函数拥有一个prototype,又是实例对象的__proto__,其constructor指向构造函数。

如果Star.prototype = {}给原型重新赋值,此时会丢失构造器,像Array,String不允许,会报错。

继承

ES6,class继承,之前需要用构造函数+原型链模拟

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }

console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }

 

其实看图就明白,__proto__就是向上查找构造函数的原型。直到object.prototype.

Function.prototype是特殊对象,native code,内部实现。上级原型是自己的原型。

prototype是每个创建出来的function生成的,成为子function的__proto__

Function.__proto__ === Function.prototype;

每个function,构造函数都有prototype原型。其constructor,构造器就是构造函数。

每个function的__proto__指向Function.prototype. Function创建构造函数。function。

每个 Function 的实例的 __proto__ 都指向了 Function.prototype(原型),函数原型(Function.prototype)的 __proto__ 指向了 Object.prototype(对象的原型)
Function是特殊函数,可以称作是所有函数的爸爸,Object()也是Function创建的。

Function和Object的关系

这是JavaScript比较奇葩的一个地方,也是不太让人容易接受的一点。

我们知道一般任何对象都是Object的instance,因为原型链的顶端都指向Object.prototype。那么Object本身是什么?Object也是个函数,而任何函数都是Function的实例对象,比如Array,String,当然Object也包括在内,它也是Function的实例,即:

Object.__proto__ === Function.prototype;
Object instanceof Function === true

这样就有了一个JavaScript里经常说到的蛋鸡问题:

Object instanceof Function === true
Function instanceof Object === true

 

应用

扯了这么多,原型,原型链到底什么用,用于实现继承。方法公用

举例

a)Student 继承Person b)Person 包含一个实例变量 name, 包含一个方法 printName c)Student 包含一个实例变量 score, 包含一个实例方法printScore d)所有Person和Student对象之间共享一个方法

es6类写法

    class Person {
        constructor(name) {
            this.name = name;
        }
        printName() {
            console.log('This is printName');
        }
        commonMethods(){
            console.log('我是共享方法');
        }
    }

    class Student extends Person {
        constructor(name, score) {
            super(name);
            this.score = score;
        }
        printScore() {
            console.log('This is printScore');
        }
    }

    let stu = new Student('小红');
    let person = new Person('小紫');
    console.log(stu.commonMethods===person.commonMethods);//true
复制代码

原生写法

    function Person (name){
        this.name = name;
        this.printName=function() {
            console.log('This is printName');
        };
    }
    Person.prototype.commonMethods=function(){
        console.log('我是共享方法');
    };

    function Student(name, score) {
        Person.call(this,name);
        this.score = score;
        this.printScore=function() {
            console.log('This is printScore');
        }
    }
    Student.prototype = new Person();
    let person = new Person('小紫',80);
    let stu = new Student('小红',100);
    console.log(stu.printName===person.printName);//false
    console.log(stu.commonMethods===person.commonMethods);//true

Person.prototype.xxx

Person.call(this.name)

发表评论

邮箱地址不会被公开。