js注意事项2(原型原型链Object相关)

Posted 嘿起屁儿整

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js注意事项2(原型原型链Object相关)相关的知识,希望对你有一定的参考价值。

原型原型链

什么是原型? prototype

js中,一切皆对象,除了null和undefined。所有对象都有隐式__proto__属性
java/php都有class类,js没有class类概念,js通过function函数模拟的class类,然后通过new实例化构造器函数

  • 对象分为普通对象,和函数对象
  • 普通对象没有prototype原型 ,直接调用__proto__
  • 函数对象都有prototype原型,直接调用prototype
  • Object函数对象是所有函数对象的顶层

通过prototype原型可以定义公共方法或属性,比如Person.prototype.sayhi=“itisok”,那么这个sayhi称为原型对象

用let const var 直接定义的都是普通对象,通过new Object新建的对象也是普通对象
Object、Array、Function、Date、自定义函数 等都属于函数对象
Object的原型就是Object(其中常见方法toString等)
Array的原型就是Array (其中常见方法push、pop等)
Date的原型就是Date (其中常见方法getFullYear、getMonth等)
Function的原型就是function空函数所以他的原型对象没有东西
自定义函数比较特殊,不指定原型默认Object,通过prototype指定后,则原型为指定内容

 		// 普通对象
        var obj = { a: "111", b: "222" }
        console.log(obj.prototype, obj.__proto__) //undefined  >Object
        var arr = [1, 2, 3]
        console.log(arr.prototype, arr.__proto__) //undefined  >Array(0)
        let a = 3
        console.log(a.prototype, a.__proto__)     //undefined  >Number
        const str = "asdflkj"
        console.log(str.prototype, str.__proto__) //undefined  >String
        let o2 = new Object();
        console.log(o2.prototype, o2.__proto__)   //undefined  >Object
        let vue = new Vue({ el: "#app" })
        console.log(vue.prototype, vue.__proto__) //undefined  >Object

        // 函数对象
        console.log(Object.prototype, Object.__proto__)       //>Object  ƒ(){[native code]}
        console.log(Array.prototype, Array.__proto__);        //>Array(0) ƒ(){[native code]}
        console.log(Function.prototype, Function.__proto__);  //ƒ(){[native code]} ƒ(){[native code]}
        function hello() { }
        console.log(hello.prototype, hello.__proto__) //>Object   ƒ(){[native code]}
        hello.prototype = "helloworld";
        console.log(hello.prototype, hello.__proto__) //helloworld ƒ(){[native code]}

什么是原型对象(构造函数、原型属性或方法、proto

原型对象:比如Person.prototype或p. __ proto__ ,输出的就是原型对象。
包括:原型属性、constructor、__ proto__
原型属性:比如一个函数对象Person,Person.prototype.sayhi=“helloworld”,那么这个sayhi就是原型属性
constructor:构造函数。比如function Person(name,age){this.name=“张三”,this.age=18},那么这个函数对象这个整体就是构造函数
__ proto__:代表此原型对象的原型对象。比如Person.prototype.__ proto__那么就指向Object.prototype 这个原型对象。跟原型链有关,用于向上找方法或属性

什么是原型链?

原型链:每一个对象都有原型对象,原型对象也有他的原型对象。当一个对象调用属性或方法时,先从自身找,没有则再朝上层找,直到null(比如Person中找不到的方法,就会到Object找,再找不到就说明没有)

直接定义一个对象,
他的原型链:obj->Object.prototype->null

var obj = { a: 123, b: 456 }
console.log(obj.__proto__ === Object.prototype) //true
通过构造函数(Person) new一个对象,
他的原型链:p->Person.prototype->Object.prototype->null

function Person(name) {
	this.name = name;
}
let p = new Person("张三")
console.log(p.__proto__ === Person.prototype, Person.prototype.__proto__ === Object.prototype) //true true
当你需要父类的属性和方法时,你可以把它的原型指向父类的原型。此时的原型链就是:
child -> Parent.prototype -> Object.prototype -> null

function Parent(){
	this.name = "我是父亲";
}
Parent.prototype = {age:24};
function Child(){
	this.name = "我是儿子";
}
Child.prototype = Object.create(Parent.prototype); 
//让Child的原型指向Parent的原型
Child.prototype.constructor = Child; 
//把child的构造函数指向回来,否则它将指向Parent。
虽然在这没什么影响,但要养成代码的严谨性

var child = new Child();
console.log(child.name); //我是儿子
console.log(child.age); //24
console.log(child.toString()); //[object Object]
数组也是一个对象,不过它是由Array构造函数new而来的,
所以他的原型链:arr->Array.prototype->Object.prototype->null

var arr = [1,2,3];
函数也是一个对象,不过它是由Function构造函数new而来的,
所以他的原型链:fn->Function.prototype->Object.prototype->null
var fun = function(){}

prototype和__proto__的区别?

函数的prototype指向原型对象,实例的__proto__指向原型对象
那么函数的prototype.__proto__指向原型对象的原型对象,即指向Object顶级的prototype
那么Object.prototype.__proto__为null,所以原型链到此结束

原型链结论:每一个对象都有原型对象,原型对象也有他的原型对象。当一个对象调用属性或方法时,先从自身找,没有则再朝上层找,直到null(比如Person中找不到的方法,就会到Object找,再找不到就说明没有)

		function Person(name,age) {
            this.name = name;
            this.age = age;
        }
        Person.prototype.sayhi="itisok"
        let p = new Person("张三")
        console.log(Person.prototype===p.__proto__) //true 都指向sayhi这个原型对象

constructor与上面两个有什么联系

constructor就是构造函数本体
比如 function Person(name,age) {
this.name = name;
this.age = age;
} 这个整体就是构造函数

		function Person(name,age) {
            this.name = name;
            this.age = age;
        }
        Person.prototype.sayhi="itisok"
        let p = new Person("张三")
        console.log(Person.prototype.constructor===p.__proto__.cunstructor) 
        //true,都指向function Person(name,age) {
        //    this.name = name;
        //    this.age = age;
        //}   这个构造函数

原型对象:(例如Person.prototype或p.proto包含原型属性(例如sayhi)、constructor、 和__proto__

查看Object属性方法

直接在控制台输入 Object.prototype 查看他的constructor构造函数

instanceof判断实例是否属于函数(或者说判断实例是否出现在函数的原型链任意位置)

function Person(name,age) {
	this.name = name;
	this.age = age;
}
let p = new Person("张三")

console.log(p instanceof Person) //true
console.log(Person instanceof Object) //true
console.log(p instanceof Object) //true

hasOwnProperty判断构造函数是否有此本地属性(或者说Person构造函数中是否定义此字段)

function Person(name,age) {
	this.name = name;
	this.age = age;
}
console.log(Person.hasOwnProperty("age")) //true

以上是关于js注意事项2(原型原型链Object相关)的主要内容,如果未能解决你的问题,请参考以下文章

图解Javascript原型链

JavaScript原型链分析

JS继承

JS 对象(Object)的深入解析—原型属性

理解js中是原型链? 如何实现继承?

js原型和原型链