Prototype Prototype chain and (c)

VII. Function object (review the previous knowledge)

All function objects of proto point Function.prototype, it is an empty function (Empty function)
Number.__proto__ === Function.prototype  // true
Number.constructor == Function //true Boolean.__proto__ === Function.prototype // true Boolean.constructor == Function //true String.__proto__ === Function.prototype // true String.constructor == Function //true // 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身 Object.__proto__ === Function.prototype // true Object.constructor == Function // true // 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身 Function.__proto__ === Function.prototype // true Function.constructor == Function //true Array.__proto__ === Function.prototype // true Array.constructor == Function //true RegExp.__proto__ === Function.prototype // true RegExp.constructor == Function //true Error.__proto__ === Function.prototype // true Error.constructor == Function //true Date.__proto__ === Function.prototype // true Date.constructor == Function //true 

JavaScript has built (build-in) constructor / total of 12 objects (the ES5 newly added JSON), where lists accessible eight constructor. The rest can not directly access such as Global, Arguments only created when the function is called by JS engine, Math, JSON is present in the form of an object without new. Their proto is Object.prototype. as follows

Math.__proto__ === Object.prototype  // true
Math.construrctor == Object // true JSON.__proto__ === Object.prototype // true JSON.construrctor == Object //true 

The above said function object course include custom. as follows

// 函数声明
function Person() {} // 函数表达式 var Perosn = function() {} console.log(Person.__proto__ === Function.prototype) // true console.log(Man.__proto__ === Function.prototype) // true 

What is this indicating?

** All are from the constructor Function.prototype, even including the root builder Objectand Functionitself. All constructors inherit properties and methods · · Function.prototype of. The length, call, apply, bind **

(You should see the first sentence, the second sentence in the next section we continue to say, first dig a hole :))
Function.prototypeand only typeof XXX.prototypeas functionof prototype. Other constructor prototypeis an object (the reasons already explained in section III). As follows (and review it again):

console.log(typeof Function.prototype) // function
console.log(typeof Object.prototype) // object console.log(typeof Number.prototype) // object console.log(typeof Boolean.prototype) // object console.log(typeof String.prototype) // object console.log(typeof Array.prototype) // object console.log(typeof RegExp.prototype) // object console.log(typeof Error.prototype) // object console.log(typeof Date.prototype) // object console.log(typeof Object.prototype) // object 

Oh, also mentioned above, it is an empty function, console.log(Function.prototype)look at the next (pay attention, the next section will tell you this)

Know all constructors (with built-in and custom) of __proto__all Function.prototype, it Function.prototype's __proto__who is it?
I believe all heard the JavaScript function is also first-class citizens, then how can reflect from it? Following
console.log(Function.prototype.__proto__ === Object.prototype) // true
this description of all constructors it is also a common JS object to the constructor may add / delete attributes. It also inherits all the methods on the Object.prototype: toString, valueOf, hasOwnProperty and so on. (You should also understand that the first sentence, the second sentence in the next section we continue to say, no digging, or just the pit;))

Finally Object.prototype of proto Who is?
Object.prototype.__proto__ === null // true
It has peaked, and is null. (Read now, go back and look at the fifth chapter, can understand it?)

Eight. Prototype

In all of the attributes defined in ECMAScript core, should the number of the most intriguing prototypeattribute of. For ECMAScript is a reference type, prototypeit is preserved in all instances they are where the real methods. In other words he said, such toString()and valuseOf()other methods are actually stored in prototypename, but by their own instance of the object access only.

- "JavaScript Advanced Programming" third edition P116

We know that JS built some of the ways for us to use, such as:
the object can be used constructor/toString()/valueOf()other methods;
Arrays can use map()/filter()/reducer()other methods;
figures available with parseInt()/parseFloat()other methods;
Why? ? ?

 
why??

 

When we create a function:

var Person = new Object()
PersonIs Objectan instance, it Person inherits the Objectprototype object Object.prototypeof all the methods:

 

 
 
Object.prototype

Each instance of Object having the above properties and methods.
So I can Person.constructor also be used Person.hasOwnProperty .

 

When we create an array:

var num = new Array()
numIs Arrayan instance, it num inherits the Arrayprototype object Array.prototypeof all the methods:

 

 

Array.prototype

 

Are you f *** ing kidding me? This is how Nima an empty array? ? ?

 

 

doge

We can use a new method of providing ES5: Object.getOwnPropertyNames
Get all ( including non-enumerable attribute ) attribute names are not included prototyin the property returns an array:

 

var arrayAllKeys = Array.prototype; // [] 空数组
// 只得到 arrayAllKeys 这个对象里所有的属性名(不会去找 arrayAllKeys.prototype 中的属性)
console.log(Object.getOwnPropertyNames(arrayAllKeys)); /* 输出: ["length", "constructor", "toString", "toLocaleString", "join", "pop", "push", "concat", "reverse", "shift", "unshift", "slice", "splice", "sort", "filter", "forEach", "some", "every", "map", "indexOf", "lastIndexOf", "reduce", "reduceRight", "entries", "keys", "copyWithin", "find", "findIndex", "fill"] */ 

So you will understand just declare an array, why it can be so much way to go.

Careful you must find the Object.getOwnPropertyNames(arrayAllKeys)array's output is not constructor/hasOwnPrototypesuch as object methods (you certainly did not find).
But an array of casual defined also use these methods

var num = [1];
console.log(num.hasOwnPrototype()) // false (输出布尔值而不是报错)

Why ???


 
why??

Because Array.prototypealthough these methods did not, but it has a prototype object ( __proto__):

// 上面我们说了 Object.prototype 就是一个普通对象。
Array.prototype.__proto__ == Object.prototype

So Array.prototypeinherits all object methods, when you use num.hasOwnPrototype()the time, JS will first check its constructor ( Array) prototype object Array.prototypethere have hasOwnPrototype()methods, not found, then continue to check Array.prototypethe prototype object Array.prototype.__proto__there is no such method.

When we create a function:

var f = new Function("x","return x*x;"); //当然你也可以这么创建 f = function(x){ return x*x } console.log(f.arguments) // arguments 方法从哪里来的? console.log(f.call(window)) // call 方法从哪里来的? console.log(Function.prototype) // function() {} (一个空的函数) console.log(Object.getOwnPropertyNames(Function.prototype)); /* 输出 ["length", "name", "arguments", "caller", "constructor", "bind", "toString", "call", "apply"] */ 

Let us review the eighth section of this sentence:

所有函数对象proto都指向 Function.prototype,它是一个空函数(Empty function)

嗯,我们验证了它就是空函数。不过不要忽略前半句。我们枚举出了它的所有的方法,所以所有的函数对象都能用,比如:

 

 

函数对象

 

如果你还没搞懂啥是函数对象?


 

还有,我建议你可以再复习下为什么:

Function.prototype 是唯一一个typeof XXX.prototype为 “function”的prototype

我猜你肯定忘了。

九. 复习一下

第八小节我们总结了:

所有函数对象的 __proto__ 都指向 Function.prototype,它是一个空函数(Empty function)

但是你可别忘了在第三小节我们总结的:

所有对象的 __proto__ 都指向其构造器的 prototype

咦,我找了半天怎么没找到这句话……


 
doge | center

我们下面再复习下这句话。

先看看 JS 内置构造器:

var obj = {name: 'jack'}
var arr = [1,2,3] var reg = /hello/g var date = new Date var err = new Error('exception') console.log(obj.__proto__ === Object.prototype) // true console.log(arr.__proto__ === Array.prototype) // true console.log(reg.__proto__ === RegExp.prototype) // true console.log(date.__proto__ === Date.prototype) // true console.log(err.__proto__ === Error.prototype) // true 

再看看自定义的构造器,这里定义了一个 Person

function Person(name) {
  this.name = name; } var p = new Person('jack') console.log(p.__proto__ === Person.prototype) // true 

pPerson 的实例对象,p 的内部原型总是指向其构造器 Person 的原型对象 prototype

每个对象都有一个 constructor 属性,可以获取它的构造器,因此以下打印结果也是恒等的:

function Person(name) {
    this.name = name } var p = new Person('jack') console.log(p.__proto__ === p.constructor.prototype) // true 

上面的Person没有给其原型添加属性或方法,这里给其原型添加一个getName方法:

function Person(name) {
    this.name = name } // 修改原型 Person.prototype.getName = function() {} var p = new Person('jack') console.log(p.__proto__ === Person.prototype) // true console.log(p.__proto__ === p.constructor.prototype) // true 

可以看到p.__proto__Person.prototypep.constructor.prototype都是恒等的,即都指向同一个对象。

如果换一种方式设置原型,结果就有些不同了:

function Person(name) {
    this.name = name } // 重写原型 Person.prototype = { getName: function() {} } var p = new Person('jack') console.log(p.__proto__ === Person.prototype) // true console.log(p.__proto__ === p.constructor.prototype) // false 

这里直接重写了 Person.prototype(注意:上一个示例是修改原型)。输出结果可以看出p.__proto__仍然指向的是Person.prototype,而不是p.constructor.prototype

这也很好理解,给Person.prototype赋值的是一个对象直接量{getName: function(){}},使用对象直接量方式定义的对象其构造器(constructor)指向的是根构造器ObjectObject.prototype是一个空对象{}{}自然与{getName: function(){}}不等。如下:

var p = {}
console.log(Object.prototype) // 为一个空的对象{}
console.log(p.constructor === Object) // 对象直接量方式定义的对象其constructor为Object console.log(p.constructor.prototype === Object.prototype) // 为true,不解释(๑ˇ3ˇ๑) 

十. 原型链(再复习一下:)

下面这个例子你应该能明白了!

function Person(){}
var person1 = new Person(); console.log(person1.__proto__ === Person.prototype); // true console.log(Person.prototype.__proto__ === Object.prototype) //true console.log(Object.prototype.__proto__) //null Person.__proto__ == Function.prototype; //true console.log(Function.prototype)// function(){} (空函数) var num = new Array() console.log(num.__proto__ == Array.prototype) // true console.log( Array.prototype.__proto__ == Object.prototype) // true console.log(Array.prototype) // [] (空数组) console.log(Object.prototype.__proto__) //null console.log(Array.__proto__ == Function.prototype)// true 

疑点解惑:

  1. Object.__proto__ === Function.prototype // true
    Object 是函数对象,是通过new Function()创建的,所以Object.__proto__指向Function.prototype。(参照第八小节:「所有函数对象的__proto__都指向Function.prototype」)

  2. Function.__proto__ === Function.prototype // true
    Function 也是对象函数,也是通过new Function()创建,所以Function.__proto__指向Function.prototype

自己是由自己创建的,好像不符合逻辑,但仔细想想,现实世界也有些类似,你是怎么来的,你妈生的,你妈怎么来的,你姥姥生的,……类人猿进化来的,那类人猿从哪来,一直追溯下去……,就是无,(NULL生万物)
正如《道德经》里所说“无,名天地之始”。

  1. Function.prototype.__proto__ === Object.prototype //true

其实这一点我也有点困惑,不过也可以试着解释一下。
Function.prototype是个函数对象,理论上他的__proto__应该指向 Function.prototype,就是他自己,自己指向自己,没有意义。
JS一直强调万物皆对象,函数对象也是对象,给他认个祖宗,指向Object.prototypeObject.prototype.__proto__ === null,保证原型链能够正常结束。

十一 总结

  • 原型和原型链是JS实现继承的一种模型。
  • 原型链的形成是真正是靠__proto__ 而非prototype

要深入理解这句话,我们再举个例子,看看前面你真的理解了吗?

 var animal = function(){};
 var dog = function(){}; animal.price = 2000; dog.prototype = animal; var tidy = new dog(); console.log(dog.price) //undefined console.log(tidy.price) // 2000 

这里解释一下:

 var dog = function(){};
 dog.prototype.price = 2000; var tidy = new dog(); console.log(tidy.price); // 2000 console.log(dog.price); //undefined 
 var dog = function(){};
 var tidy = new dog(); tidy.price = 2000; console.log(dog.price); //undefined 

这个明白吧?想一想我们上面说过这句话:

实例(tidy)和 原型对象(dog.prototype)存在一个连接。不过,要明确的真正重要的一点就是,这个连接存在于实例(tidy)与构造函数的原型对象(dog.prototype)之间,而不是存在于实例(tidy)与构造函数(dog)之间。

聪明的你肯定想通了吧 




Guess you like

Origin www.cnblogs.com/niuzijie/p/11262007.html