Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript prototype是如何工作的?_Javascript_Dynamic Languages_Prototype Oriented - Fatal编程技术网

Javascript prototype是如何工作的?

Javascript prototype是如何工作的?,javascript,dynamic-languages,prototype-oriented,Javascript,Dynamic Languages,Prototype Oriented,我不太喜欢动态编程语言,但我已经编写了相当多的JavaScript代码。我从来没有真正了解过这种基于原型的编程,有人知道它是如何工作的吗 var obj = new Object(); obj.prototype.test = function() { alert('Hello?'); }; var obj2 = new obj(); obj2.test(); 我记得不久前我和人们进行了很多讨论(我不确定我在做什么),但据我所知,没有课堂的概念。它只是一个对象,这些对象的实例是原始对象的克隆,

我不太喜欢动态编程语言,但我已经编写了相当多的JavaScript代码。我从来没有真正了解过这种基于原型的编程,有人知道它是如何工作的吗

var obj = new Object();
obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();
我记得不久前我和人们进行了很多讨论(我不确定我在做什么),但据我所知,没有课堂的概念。它只是一个对象,这些对象的实例是原始对象的克隆,对吗

但是JavaScript中这个“.prototype”属性的确切用途是什么?它与实例化对象有什么关系

更新:正确的方法
此外,这些工具确实帮助很大。

prototype
允许您创建类。如果不使用
prototype
,则它将成为静态的

下面是一个简短的例子

var obj = new Object();
obj.test = function() { alert('Hello?'); };
在上述情况下,您有静态函数调用测试。此函数只能由obj.test访问,您可以将obj想象为一个类

如以下代码所示

function obj()
{
}

obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();
obj已经成为一个现在可以实例化的类。obj可以存在多个实例,它们都具有
test
功能


以上是我的理解。我正在把它变成一个社区wiki,这样人们可以在我错的时候纠正我。

prototype
允许你创建类。如果不使用
prototype
,则它将成为静态的

下面是一个简短的例子

var obj = new Object();
obj.test = function() { alert('Hello?'); };
在上述情况下,您有静态函数调用测试。此函数只能由obj.test访问,您可以将obj想象为一个类

如以下代码所示

function obj()
{
}

obj.prototype.test = function() { alert('Hello?'); };
var obj2 = new obj();
obj2.test();
obj已经成为一个现在可以实例化的类。obj可以存在多个实例,它们都具有
test
功能

以上是我的理解。我把它变成了一个社区维基,所以如果我错了,人们可以纠正我

此“.prototype”属性的确切用途是什么

标准类的接口变得可扩展。例如,您正在使用
数组
类,并且还需要为所有数组对象添加自定义序列化程序。你会花时间编写一个子类,还是使用合成或。。。prototype属性通过让用户控制类可用的确切成员/方法集来解决这个问题

将原型视为一个额外的vtable指针。当原始类中缺少某些成员时,将在运行时查找原型

此“.prototype”属性的确切用途是什么

标准类的接口变得可扩展。例如,您正在使用
数组
类,并且还需要为所有数组对象添加自定义序列化程序。你会花时间编写一个子类,还是使用合成或。。。prototype属性通过让用户控制类可用的确切成员/方法集来解决这个问题


将原型视为一个额外的vtable指针。当原始类中缺少一些成员时,将在运行时查找原型。

Javascript没有通常意义上的继承,但它具有原型链

原型链 如果在对象中找不到对象的成员,则会在原型链中查找该成员。链由其他对象组成。可以使用
\uuuu proto\uuu
变量访问给定实例的原型。每个对象都有一个,因为javascript中的类和实例之间没有区别

向原型中添加函数/变量的优点是,它必须只在内存中存在一次,而不是针对每个实例


它对于继承也很有用,因为原型链可以由许多其他对象组成。

Javascript没有通常意义上的继承,但它有原型链

原型链 如果在对象中找不到对象的成员,则会在原型链中查找该成员。链由其他对象组成。可以使用
\uuuu proto\uuu
变量访问给定实例的原型。每个对象都有一个,因为javascript中的类和实例之间没有区别

向原型中添加函数/变量的优点是,它必须只在内存中存在一次,而不是针对每个实例

它对于继承也很有用,因为原型链可以由许多其他对象组成。

每个名为
[[prototype]]]
的JavaScript对象,其值为
null
对象
。您可以将插槽视为对象上的属性,位于JavaScript引擎内部,隐藏在您编写的代码之外。
[[Prototype]]
周围的方括号是经过深思熟虑的,是一种表示内部插槽的ECMAScript规范约定

对象的
[[Prototype]]
指向的值通俗地称为“该对象的原型”

如果您通过点(
obj.propName
)或括号(
obj['propName']
)符号访问属性,并且对象没有直接具有这样的属性(即,可以通过
obj.hasOwnProperty('propName')
进行检查的自有属性),则运行时会在
引用的对象上查找具有该名称的属性[[Prototype]]
。如果
[[Prototype]]
也没有这样的属性,则依次检查其
[[Prototype]]
,依此类推。这样,将遍历原始对象的原型链,直到找到匹配项或到达其末端。原型链顶部是
null

现代JavaScript实现允许通过以下方式读取和/或写入
[[Prototype]]

  • new
    操作符(在构造函数返回的默认对象上配置原型链)
  • 扩展了
    关键字(在使用类语法时配置原型链)
  • object [[Prototype]] → aFunction.prototype
    anObject.__proto__ === anotherObject
    
    // (1) Object.create:
    var object = Object.create(anotherObject)
    // object.__proto__ = anotherObject
    
    // (2) ES6 object initializer:
    var object = { __proto__: anotherObject };
    // object.__proto__ = anotherObject
    
    // (3) Traditional JavaScript:
    var object = new aFunction;
    // object.__proto__ = aFunction.prototype
    
    var object = Object.create(Object.prototype);
    var object = { __proto__: Object.prototype }; // ES6 only
    var object = new Object;
    
    function Person(name){
        this.name = name;
    }
    Person.prototype.getName = function(){
        console.log(this.name);
    }
    var person = new Person("George");
    
    var person = {};
    function Person(name){  this.name = name;  }
    
    function getName(){
        console.log(this.name);
    }
    
    Person("George");
    getName();//would print the "George" in the console
    
    person.Person = Person;
    person.getName = getName;
    
    person.Person("George");
    person.getName();// -->"George"
    
    Object {Person: function, getName: function, name: "George"}
    
    person.__proto__.Person = Person;
    person.__proto__.getName = getName;
    
    person.__proto__ = {
        Person: Person,
        getName: getName
    };
    
    var propertiesObject = {
        Person: Person,
        getName: getName
    };
    var person = Object.create(propertiesObject);
    
    console.log(person.__proto__===propertiesObject); //true
    
    Person.call(person, "George");
    
    //apply is more useful when params count is not fixed
    Person.apply(person, ["George"]);
    
    getName.call(person);   
    getName.apply(person);
    
    function Person(name){  this.name = name;  }
    my_person_prototype = { getName: function(){ console.log(this.name); } };
    
    var newObject = {};
    
    for(var key in my_person_prototype){
        newObject[key] = my_person_prototype[key];
    }
    
    var newObject = Object.create(my_person_prototype);
    //here you can check out the __proto__ attribute
    console.log(newObject.__proto__ === my_person_prototype); //true
    //and also check if you have access to your desired properties
    console.log(typeof newObject.getName);//"function"
    
    newObject.getName();
    
    Person.call(newObject, "George");
    
    Person.apply(newObject, ["George"]);
    
    new FunctionName()
    
    console.log(Object.prototype.__proto__===null);//true
    
    var F = function() {}
    var f = new F()
    
    f.__proto__ === F.prototype
    
     f = Object.create(proto)
    
    f.__proto__ === proto
    
    var F = function(i) { this.i = i }
    var f = new F(1)
    
    (Function)       (  F  )                                      (f)----->(1)
     |  ^             | | ^                                        |   i    |
     |  |             | | |                                        |        |
     |  |             | | +-------------------------+              |        |
     |  |constructor  | |                           |              |        |
     |  |             | +--------------+            |              |        |
     |  |             |                |            |              |        |
     |  |             |                |            |              |        |
     |[[Prototype]]   |[[Prototype]]   |prototype   |constructor   |[[Prototype]]
     |  |             |                |            |              |        |
     |  |             |                |            |              |        |
     |  |             |                | +----------+              |        |
     |  |             |                | |                         |        |
     |  |             |                | | +-----------------------+        |
     |  |             |                | | |                                |
     v  |             v                v | v                                |
    (Function.prototype)              (F.prototype)                         |
     |                                 |                                    |
     |                                 |                                    |
     |[[Prototype]]                    |[[Prototype]]          [[Prototype]]|
     |                                 |                                    |
     |                                 |                                    |
     | +-------------------------------+                                    |
     | |                                                                    |
     v v                                                                    v
    (Object.prototype)                                       (Number.prototype)
     | | ^
     | | |
     | | +---------------------------+
     | |                             |
     | +--------------+              |
     |                |              |
     |                |              |
     |[[Prototype]]   |constructor   |prototype
     |                |              |
     |                |              |
     |                | -------------+
     |                | |
     v                v |
    (null)           (Object)
    
    var f = new F(1)
    
    f.constructor === F
    !f.hasOwnProperty('constructor')
    Object.getPrototypeOf(f) === F.prototype
    F.prototype.hasOwnProperty('constructor')
    F.prototype.constructor === f.constructor
    
    class C {
        constructor(i) {
            this.i = i
        }
        inc() {
            return this.i + 1
        }
    }
    
    class D extends C {
        constructor(i) {
            super(i)
        }
        inc2() {
            return this.i + 2
        }
    }
    
    // Inheritance syntax works as expected.
    c = new C(1)
    c.inc() === 2
    (new D(1)).inc() === 2
    (new D(1)).inc2() === 3
    
    // "Classes" are just function objects.
    C.constructor === Function
    C.__proto__ === Function.prototype
    D.constructor === Function
    // D is a function "indirectly" through the chain.
    D.__proto__ === C
    D.__proto__.__proto__ === Function.prototype
    
    // "extends" sets up the prototype chain so that base class
    // lookups will work as expected
    var d = new D(1)
    d.__proto__ === D.prototype
    D.prototype.__proto__ === C.prototype
    // This is what `d.inc` actually does.
    d.__proto__.__proto__.inc === C.prototype.inc
    
    // Class variables
    // No ES6 syntax sugar apparently:
    // http://stackoverflow.com/questions/22528967/es6-class-variable-alternatives
    C.c = 1
    C.c === 1
    // Because `D.__proto__ === C`.
    D.c === 1
    // Nothing makes this work.
    d.c === undefined
    
    (c)----->(1)
     |   i
     |
     |
     |[[Prototype]]
     |
     |
     v    __proto__
    (C)<--------------(D)         (d)
    | |                |           |
    | |                |           |
    | |prototype       |prototype  |[[Prototype]] 
    | |                |           |
    | |                |           |
    | |                | +---------+
    | |                | |
    | |                | |
    | |                v v
    |[[Prototype]]    (D.prototype)--------> (inc2 function object)
    | |                |             inc2
    | |                |
    | |                |[[Prototype]]
    | |                |
    | |                |
    | | +--------------+
    | | |
    | | |
    | v v
    | (C.prototype)------->(inc function object)
    |                inc
    v
    Function.prototype
    
    c = new C(1)
    c.inc() === 2
    
    c.inc()
    
    var model = {x:2};
    var product = Object.create(model);
    model.y = 5;
    product.y
    =>5
    
    var Object= new Function ([native code for object Object])
    var String= new Function ([native code for object String])
    var Number= new Function ([native code for object Number])
    var Boolean= new Function ([native code for object Boolean])
    var Array= new Function ([native code for object Array])
    var RegExp= new Function ([native code for object RegExp])
    var Function= new Function ([native code  for object Function])
    var UserDefinedFunction= new Function ("user defined code")
    
    var a=new Object() or var a=Object() or var a={} //Create object of type Object
    var a=new String() //Create object of type String
    var a=new Number() //Create object of type Number
    var a=new Boolean() //Create object of type Boolean
    var a=new Array() or var a=Array() or var a=[]  //Create object of type Array
    var a=new RegExp() or var a=RegExp() //Create object of type RegExp
    var a=new UserDefinedFunction() 
    
    var b=new a() //error. a is not typeof==='function'
    
    var b=new Math() //error. Math is not typeof==='function'
    
    var a=String() // Create a new Non Object string. returns a typeof==='string' 
    var a=Number() // Create a new Non Object Number. returns a typeof==='number'
    var a=Boolean() //Create a new Non Object Boolean. returns a typeof==='boolean'
    
    var a=UserDefinedFunction() //may or may not create an object of type UserDefinedFunction() based on how it is defined.
    
    function UserDefinedFunction()
    {
    }
    
    UserDefinedFunction.prototype={constructor:UserDefinedFunction}
    
    function UserDefinedFunction()
    { 
    
    } 
    
    /* creating the above function automatically does the following as mentioned earlier
    
    UserDefinedFunction.prototype={constructor:UserDefinedFunction}
    
    */
    
    
    var newObj_1=new UserDefinedFunction()
    
    alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype)  //Displays true
    
    alert(newObj_1.constructor) //Displays function UserDefinedFunction
    
    //Create a new property in UserDefinedFunction.prototype object
    
    UserDefinedFunction.prototype.TestProperty="test"
    
    alert(newObj_1.TestProperty) //Displays "test"
    
    alert(Object.getPrototypeOf(newObj_1).TestProperty)// Displays "test"
    
    //Create a new Object
    
    var objA = {
            property1 : "Property1",
            constructor:Array
    
    }
    
    
    //assign a new object to UserDefinedFunction.prototype
    UserDefinedFunction.prototype=objA
    
    alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype)  //Displays false. The object referenced by UserDefinedFunction.prototype has changed
    
    //The internal reference does not change
    alert(newObj_1.constructor) // This shall still Display function UserDefinedFunction
    
    alert(newObj_1.TestProperty) //This shall still Display "test" 
    
    alert(Object.getPrototypeOf(newObj_1).TestProperty) //This shall still Display "test"
    
    
    //Create another object of type UserDefinedFunction
    var newObj_2= new UserDefinedFunction();
    
    alert(Object.getPrototypeOf(newObj_2)===objA) //Displays true.
    
    alert(newObj_2.constructor) //Displays function Array()
    
    alert(newObj_2.property1) //Displays "Property1"
    
    alert(Object.getPrototypeOf(newObj_2).property1) //Displays "Property1"
    
    //Create a new property in objA
    objA.property2="property2"
    
    alert(objA.property2) //Displays "Property2"
    
    alert(UserDefinedFunction.prototype.property2) //Displays "Property2"
    
    alert(newObj_2.property2) // Displays Property2
    
    alert(Object.getPrototypeOf(newObj_2).property2) //Displays  "Property2"
    
    var o=Starting object;
    
    do {
        alert(o + "\n" + Object.getOwnPropertyNames(o))
    
    }while(o=Object.getPrototypeOf(o))
    
    var o=Object.create(null)
    alert(Object.getPrototypeOf(o)) //Displays null
    
    function UserDefinedFunction(){}
    UserDefinedFunction.prototype=null// Can be set to any non object value (number,string,undefined etc.)
    
    var o=new UserDefinedFunction()
    alert(Object.getPrototypeOf(o)==Object.prototype)   //Displays true
    alert(o.constructor)    //Displays Function Object
    
    var keyValueStore = (function() {
        var count = 0;
        var kvs = function() {
            count++;
            this.data = {};
            this.get = function(key) { return this.data[key]; };
            this.set = function(key, value) { this.data[key] = value; };
            this.delete = function(key) { delete this.data[key]; };
            this.getLength = function() {
                var l = 0;
                for (p in this.data) l++;
                return l;
            }
        };
    
        return  { // Singleton public properties
            'create' : function() { return new kvs(); },
            'count' : function() { return count; }
        };
    })();
    
    kvs = keyValueStore.create();
    
    var keyValueStore = (function() {
        var count = 0;
        var kvs = function() {
            count++;
            this.data = {};
        };
    
        kvs.prototype = {
            'get' : function(key) { return this.data[key]; },
            'set' : function(key, value) { this.data[key] = value; },
            'delete' : function(key) { delete this.data[key]; },
            'getLength' : function() {
                var l = 0;
                for (p in this.data) l++;
                return l;
            }
        };
    
        return  {
            'create' : function() { return new kvs(); },
            'count' : function() { return count; }
        };
    })();
    
    Object.getPrototypeOf(Tree.prototype); // Object {} 
    
    Child  
    |
     \
      \
       Tree.prototype
       - branch
       |
       |
        \
         \
          Object.prototype
          -toString
          -valueOf
          -etc., etc.
    
     function Person() {}
    
    var p = new Person();
    
    Person.prototype.constructor === Person
    
    var obj = {}
    obj.a         // [[Get]] consults prototype chain
    obj.b = 20    // [[Set]] consults prototype chain
    
    function Bar(){};
    
    // Both assign Bar.prototype to b1/b2[[Prototype]]
    var b = new Bar;
    // Object.getPrototypeOf grabs the objects [[Prototype]]
    console.log(Object.getPrototypeOf(b) === Bar.prototype) // true
    
    // Get properties that are defined on this object
    console.log(Object.getOwnPropertyDescriptors(Object.prototype))
    
    var b = new Bar;
    // Get all Bar.prototype properties
    console.log(b.__proto__ === Bar.prototype)
    // Get all Object.prototype properties
    console.log(b.__proto__.__proto__ === Object.prototype)