一文详解JavaScript中prototype的使用

目录
  • prototype初步认识
  • 函数有prototype属性,函数创建的对象没有
  • 获得当前对象的属性
  • 父和子的扩展
  • 子的proto和prototype的区别
  • 扩展得到的东西到底从哪来的

prototype初步认识

在学习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变量

函数有prototype属性,函数创建的对象没有

这个时候,尝试对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属性是一样的

子的proto和prototype的区别

到这里你肯定想问,对于子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>

以上就是一文详解JavaScript中prototype的使用的详细内容,更多关于JavaScript prototype的资料请关注我们其它相关文章!

(0)

相关推荐

  • 深入理解javascript prototype的相关知识

    如图比较好的阐述了prototype和__proto__ 简单的可以这么理解: 狗类A( function foo()),狗类A的模板描述:A.模板 (foo.prototype)是一个对象object, A.模板有个构造方法 foo.prototype.constructor=function foo() 动物B(function function()), 动物B的模板描述 . B.模板 (function.prototype), B.模板有个构造方法 function.prototype.c

  • JavaScript原型Prototype详情

    目录 1.概述 1.1原型是什么 1.2获取原型 2.原型属性 2.1利用原型添加属性与方法. 2.2访问原型属性原型方法 3.自有属性与原型属性 3.1检测自有属性或者原型属性 4.isPrototypeOf()方法 5.扩展内置对象 6.结语 1.概述 1.1原型是什么 在JavaScript中,函数是一个包含属性和方法的Function类型的对象.而原型(Prototype )就是Function类型对象的一个属性. 在函数定义是包含了prototype属性,它的初始值是一个空对象 .在J

  • JS利用prototype给类添加方法操作详解

    本文实例讲述了JS利用prototype给类添加方法操作.分享给大家供大家参考,具体如下: 1.如何定义一个简单的类? 以下是一个没有任何属性和方法的类的定义: function MyClass(){}; 你可能会想,这不就是个简单的函数声明?没错,这个函数就是一个类的定义的实现.如何使用这个类呢?看下面的代码: var cls1 = new MyClass(); 这样,利用new就可以生成MyClass的一个实例了.所以在js中可以说函数就是类,类就是函数. 2.给类增加属性和方法 funct

  • 简单理解js的prototype属性及使用

    在进入正文之前,我得先说说我认识js的prototype这个东西的曲折过程. 百度js的prototype的文章,先看看,W3School关于prototype的介绍: 你觉得这概念适合定义js的prototype这个东西吗?你是否也认为prototype是一个object对象的属性呢?是的话,请认真认真看我这篇文章,因为这篇文章会毁灭你的人生三观,呵呵,就是有这么严重,因为本人就是被这个定义给害惨的. 不得不说,看了网上的一些介绍prototype的文章,基本上都说prototype是对象的一

  • js prototype深入理解及应用实例分析

    本文实例讲述了js prototype深入理解及应用.分享给大家供大家参考,具体如下: 上一篇讲了js的prototype概念,在这里回顾一下prototype的定义: prototype是函数的一个属性,并且是函数的原型对象.引用它的必然是函数,这个应该记住. 但是,很奇怪,各位看官,你有没有看过类似下面这样引用prototype的js代码: function func(){ var args = Array.prototype.slice.call(arguments, 1); return

  • 聊一聊JS中的prototype

    什么是prototype: function定义的对象有一个prototype属性,prototype属性又指向了一个prototype对象,注意prototype属性与prototype对象是两个不同的东西,要注意区别.在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身. //判断是否是数组 function isArray(obj) { ret

  • 一文详解JavaScript中prototype的使用

    目录 prototype初步认识 函数有prototype属性,函数创建的对象没有 获得当前对象的属性 父和子的扩展 子的proto和prototype的区别 扩展得到的东西到底从哪来的 prototype初步认识 在学习JavaScript中,遇到了prototype,经过一番了解,知道它是可以进行动态扩展的 function Func(){}; var func1 = new Func; console.log(func1.var1) //undefined Func.prototype.v

  • 详解Javascript中prototype属性(推荐)

    在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不是基于'类的',而是通过构造函数(constructor)和原型链(prototype chains)实现的.但是在ES6中提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类.基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能

  • 详解JavaScript中的4种类型识别方法

    具体内容如下: 1.typeof [输出]首字母小写的字符串形式 [功能] [a]可以识别标准类型(将Null识别为object) [b]不能识别具体的对象类型(Function除外) [实例] console.log(typeof "jerry");//"string" console.log(typeof 12);//"number" console.log(typeof true);//"boolean" console

  • 详解Javascript 中的 class、构造函数、工厂函数

    到了ES6时代,我们创建对象的手段又增加了,在不同的场景下我们可以选择不同的方法来建立.现在就主要有三种方法来构建对象,class关键字,构造函数,工厂函数.他们都是创建对象的手段,但是却又有不同的地方,平时开发时,也需要针对这不同来选择. 首先我们来看一下,这三种方法是怎样的 // class 关键字,ES6新特性 class ClassCar { drive () { console.log('Vroom!'); } } const car1 = new ClassCar(); consol

  • 详解JavaScript中的链式调用

    链模式 链模式是一种链式调用的方式,准确来说不属于通常定义的设计模式范畴,但链式调用是一种非常有用的代码构建技巧. 描述 链式调用在JavaScript语言中很常见,如jQuery.Promise等,都是使用的链式调用,当我们在调用同一对象多次其属性或方法的时候,我们需要多次书写对象进行.或()操作,链式调用是一种简化此过程的一种编码方式,使代码简洁.易读. 链式调用通常有以下几种实现方式,但是本质上相似,都是通过返回对象供之后进行调用. this的作用域链,jQuery的实现方式,通常链式调用

  • 详解JavaScript中的this指向问题

    题记 JS中的this指向一直是个让初学者头疼的问题.今天,我们就一起来瞅瞅this倒地是咋回事,详细说说this指向原则,从此不再为了this指向操碎了心. 开篇 首先我们都知道this是Javascript语言的一个关键字. 它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用.随着函数使用场合的不同,this的值会发生变化.但是有一个总的原则,那就是this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它所在函

  • 详解JavaScript中new操作符的解析和实现

    前言 new 运算符是我们在用构造函数创建实例的时候使用的,本文来说一下 new 运算符的执行过程和如何自己实现一个类似 new 运算符的函数. new 运算符的运行过程 new 运算符的主要目的就是为我们创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例(比如箭头函数就没有构造函数,所以是不能 new 的).new 操作符的执行大概有以下几个步骤: 创建一个新的空对象 把新对象的 __proto__ 链接到构造函数的 prototype 对象(每一个用户定义函数都有一个 proto

  • 详解JavaScript中的数据类型,以及检测数据类型的方法

    一.js中的数据类型有哪些? 在js中,基本数据类型有五种,分别是 string.number.boolean.null.undefined,不过在ES6中新增加的了一种基本数据类型Symbol(表示独一无二的值),其作用主要是从根本上防止属性名的冲突而设定的. 除了基本数据类型之外,还有引用数据类型object,也有人称之为复杂数据类型,包含了我们常见的Array.Object.Function等. 所以现在js中的数据类型共有七种. PS: Symbol数据类型通过Symbol函数生成.也就

  • 详解javascript中的Strict模式

    简介 在ES5中,引入了strict模式,我们可以称之为严格模式.相应的sloppy mode就可以被称为非严格模式. 严格模式并不是非严格模式的一个子集,相反的严格模式在语义上和非严格模式都发生了一定的变化,所以我们在使用过程中,一定要经过严格的测试.以保证在严格模式下程序的执行和非严格模式下的执行效果一致. 使用Strict mode strict mode会改变javascript的一些表现,我们将会在下一节中进行详细的讲解. 这里先来看一下,怎么使用strict mode. Strict

  • 一文详解JS中的事件循环机制

    目录 前言 1.JavaScript是单线程的 2.同步和异步 3.事件循环 前言 我们知道JavaScript 是单线程的编程语言,只能同一时间内做一件事,按顺序来处理事件,但是在遇到异步事件的时候,js线程并没有阻塞,还会继续执行,这又是为什么呢?本文来总结一下js 的事件循环机制. 1.JavaScript是单线程的 JavaScript 是一种单线程的编程语言,只有一个调用栈,决定了它在同一时间只能做一件事.在代码执行的时候,通过将不同函数的执行上下文压入执行栈中来保证代码的有序执行.在

随机推荐