在学习JavaScript中,遇到了prototype,经过一番了解,知道它是可以进行动态扩展的
function Func(){}; var func1 = new Func; console.log(func1.var1) //undefined Func.prototype.var1 = "Func进行了扩展" console.log(func1.var1) //Func进行了扩展
即最开始创建的函数Func并没有var1变量,但是我们可以进行扩展,并且让根据其创建的对象也有var1变量
这个时候,尝试对var1变量进行扩展,但是居然报错了
function Func(){}; var func1 = new Func; console.log(func1.var1) //undefined Func.prototype.var1 = "Func进行了扩展" console.log(func1.var1) //Func进行了扩展 console.log(Func.var1) func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1')
那我们现在有一个疑问:func1应该是有var1变量的,那上面报错意思是func1没有prototype属性/方法咯?我如何查看一个对象到底有没有这个属性呢?
我们知道,可以用in来查看对象是否有属性
function Func(){}; var func1 = new Func; console.log(func1.var1) //undefined Func.prototype.var1 = "Func进行了扩展" console.log(func1.var1) //Func进行了扩展 console.log(Func.var1) // func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1') console.log("var1" in func1) //true console.log("prototype" in func1) //false
现在我们知道了,func1确实没有prototype属性/方法,那func1也就是函数创建的对象都不能扩展了吗?回答这个问题之前,我们还要明白一个问题,func1中的var1变量是自己的吗?怎么区分呢?
function Func(){}; var func1 = new Func; console.log(func1.var1) //undefined Func.prototype.var1 = "Func进行了扩展" console.log(func1.var1) //Func进行了扩展 console.log(Func.var1) // func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1') console.log("var1" in func1) //true console.log("prototype" in func1) //false console.log("-----接下来看hasOwnProperty函数-----") func1.var2 = "func1自己的变量" console.log(func1.hasOwnProperty("var2")) //true console.log(func1.hasOwnProperty("var1")) //false
我们可以用hasOwnProperty
函数来知道变量是不是扩展的了
这里我把Func当成父,把func1当成子来作为个人理解
function Func() { }; var func1 = new Func; console.log(func1.var1) //undefined Func.prototype.var1 = "Func进行了扩展" console.log(func1.var1) //Func进行了扩展 console.log(Func.var1) // func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1') console.log("var1" in func1) //true console.log("prototype" in func1) //false console.log("-----接下来看hasOwnProperty函数-----") func1.var2 = "func1自己的变量" console.log(func1.hasOwnProperty("var2")) //true console.log(func1.hasOwnProperty("var1")) //false console.log("-----接下来看proto-----") console.log(Func.hasOwnProperty("__proto__")) //false console.log(func1.hasOwnProperty("__proto__")) //false console.log(func1.__proto__ === Func.prototype) // true console.log(func1.__proto__ == Func.prototype) // true console.log(func1.prototype == Func.prototype) // false console.log(func1.__proto__.var1) //Func进行了扩展 console.log(func1.var1) //Func进行了扩展
这里可以看到func1本身没有__proto__
属性,但是和Func的protype属性是一样的
到这里你肯定想问,对于子func1的__proto__
和prototype有什么区别呢?
首先子func1并没有prototype属性
其实双下划线表示隐藏的,不太想让外界访问到,这么思考,父Func不仅创建了子func1,而且创建了子func2,这时候如果子func1通过__proto__
修改了var1,那么父Func的var1跟着变化,并且func2的var1也会变化,但是如果func1直接修改var1,那么父Func和子func2的var1都不会变化
function Func() { }; var func1 = new Func; console.log(func1.var1) //undefined Func.prototype.var1 = "Func进行了扩展" console.log(func1.var1) //Func进行了扩展 console.log(Func.var1) // func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1') console.log("var1" in func1) //true console.log("prototype" in func1) //false console.log("-----接下来看hasOwnProperty函数-----") func1.var2 = "func1自己的变量" console.log(func1.hasOwnProperty("var2")) //true console.log(func1.hasOwnProperty("var1")) //false console.log("-----接下来看proto-----") console.log(Func.hasOwnProperty("__proto__")) //false console.log(func1.hasOwnProperty("__proto__")) //false console.log(func1.__proto__ === Func.prototype) // true console.log(func1.__proto__ == Func.prototype) // true console.log(func1.prototype == Func.prototype) // false console.log(func1.__proto__.var1) //Func进行了扩展 console.log(func1.var1) //Func进行了扩展 console.log("-----接下来看proto和prototype的区别-----") func1.var1 = "func1进行了扩展" console.log(func1.var1) //func1进行了扩展 console.log(Func.prototype.var1) //Func进行了扩展
那么子func1我们前面使用了hasOwnProperty属性,但是func1本身并没有这个属性,那么它从哪来的?
function Func() { }; var func1 = new Func; console.log(func1.var1) //undefined Func.prototype.var1 = "Func进行了扩展" console.log(func1.var1) //Func进行了扩展 console.log(Func.var1) // func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1') console.log("var1" in func1) //true console.log("prototype" in func1) //false console.log("-----接下来看hasOwnProperty函数-----") func1.var2 = "func1自己的变量" console.log(func1.hasOwnProperty("var2")) //true console.log(func1.hasOwnProperty("var1")) //false console.log("-----接下来看proto-----") console.log(Func.hasOwnProperty("__proto__")) //false console.log(func1.hasOwnProperty("__proto__")) //false console.log(func1.__proto__ === Func.prototype) // true console.log(func1.__proto__ == Func.prototype) // true console.log(func1.prototype == Func.prototype) // false console.log(func1.__proto__.var1) //Func进行了扩展 console.log(func1.var1) //Func进行了扩展 console.log("-----接下来看proto和prototype的区别-----") func1.var1 = "func1进行了扩展" console.log(func1.var1) //func1进行了扩展 console.log(Func.prototype.var1) //Func进行了扩展 console.log("-----接下来看hasOwnProperty从哪来的-----") console.log(Func.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true console.log(Func.__proto__.hasOwnProperty("hasOwnProperty")) // false console.log(func1.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true
从父和子那节的那张图也可以看出,使用两次__proto__
即可找到hasOwnProperty属性
那么到此也就了解了prototype和__proto__
了
附上完整代码两段供测试:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> function Fun(){ } var func1 = new Fun() console.log(typeof Fun) // function console.log(typeof func1) // object console.log(func1.prototype) // undefined console.log(typeof func1.__proto__) // object console.log(func1.__proto__) // 一个比较复杂的object console.log(func1.__proto__ == Fun.prototype) // true console.log(func1.prototype == Fun.prototype) // false Fun.prototype.var1 = "hello" console.log(func1.var1) // hello console.log(func1.__proto__.var1) // hello func1.var1 = "yes" console.log(Fun.var1) // undefined console.log(func1.var1) // yes console.log(Fun.prototype.var1) // hello console.log(func1.__proto__.var1) // hello console.log(func1.prototype) // undefined func1.__proto__.var1 = "hhh" console.log(func1.__proto__.var1) // hhh console.log(Fun.prototype.var1) // hhh console.log(Fun.__proto__.var1) // undefined console.log("------测试原型对象里面的proto-------") console.log(func1.hasOwnProperty("var1")) // true console.log(func1.hasOwnProperty("__proto__")) console.log(Fun.hasOwnProperty("hasOwnProperty")) // false console.log(Fun.hasOwnProperty("__proto__")) // false console.log(Fun.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true console.log(Fun.__proto__.hasOwnProperty("hasOwnProperty")) // false console.log(func1.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> function Func() { }; var func1 = new Func; console.log(func1.var1) //undefined Func.prototype.var1 = "Func进行了扩展" console.log(func1.var1) //Func进行了扩展 console.log(Func.var1) // func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1') console.log("var1" in func1) //true console.log("prototype" in func1) //false console.log("-----接下来看hasOwnProperty函数-----") func1.var2 = "func1自己的变量" console.log(func1.hasOwnProperty("var2")) //true console.log(func1.hasOwnProperty("var1")) //false console.log("-----接下来看proto-----") console.log(Func.hasOwnProperty("__proto__")) //false console.log(func1.hasOwnProperty("__proto__")) //false console.log(func1.__proto__ === Func.prototype) // true console.log(func1.__proto__ == Func.prototype) // true console.log(func1.prototype == Func.prototype) // false console.log(func1.__proto__.var1) //Func进行了扩展 console.log(func1.var1) //Func进行了扩展 console.log("-----接下来看proto和prototype的区别-----") func1.var1 = "func1进行了扩展" console.log(func1.var1) //func1进行了扩展 console.log(Func.prototype.var1) //Func进行了扩展 console.log("-----接下来看hasOwnProperty从哪来的-----") console.log(Func.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true console.log(Func.__proto__.hasOwnProperty("hasOwnProperty")) // false console.log(func1.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true </script> </body> </html>