资讯专栏INFORMATION COLUMN

非科班如何理解闭包,原型,原型链,继承

xuexiangjys / 598人阅读

摘要:闭包,原型,原型链,继承对象若干属性的集合输出的集中类型标识,其中上面的四种属于简单的值类型,不是对象。在实际应用中如何区分一个属性到底是基本的还是从原型中找到的呢,特别是在循环中由于所有的对象的原型链都会找到,因此所有的对象都会有的方法。

闭包,原型,原型链,继承

对象——若干属性的集合

typeof输出的集中类型标识,
其中上面的四种(undefined, number, string, boolean)属于简单的值类型,不是对象。
剩下的几种情况——函数、数组、对象、null、new Number(10)都是对象。他们都是引用类型。

判断一个变量是不是对象非常简单。值类型的类型判断用typeof,引用类型的类型判断用instanceof。

一切(引用类型)都是对象,对象是属性的集合

函数和对象的关系

(鸡生蛋蛋生鸡)
对象都是通过函数创建的

console.log(typeof (Object));  // function
console.log(typeof (Array));  // function
prototype原型

javascript默认的给函数一个属性——prototype。每个函数都有一个属性叫做prototype。
这个prototype的属性值是一个对象(属性的集合,再次强调!),默认的只有一个叫做constructor的属性,指向这个函数本身。

每个对象都有一个隐藏的属性——“__proto__”,这个属性引用了创建这个对象的函数的prototype。

这里的"__proto__"成为“隐式原型”

隐式原型__proto__

每个函数function都有一个prototype,即原型。
每个对象都有一个__proto__,可成为隐式原型。

(这个__proto__是一个隐藏的属性,javascript不希望开发者用到这个属性值,有的低版本浏览器甚至不支持这个属性值。所以你在Visual Studio 2012这样很高级很智能的编辑器中,都不会有__proto__的智能提示,但是你不用管它,直接写出来就是了。)

每个对象都有一个__proto__属性,指向创建该对象的函数的prototype

Object.prototype确实一个特例——它的__proto__指向的是null

Object.__proto__ === Function.prototype

Function是被自身创建的。所以它的__proto__指向了自身的Prototype

Function.prototype指向的对象,它的__proto__也指向Object.prototype

instanceof

typeof在判断到引用类型的时候,返回值只有object/function,你不知道它到底是一个object对象,还是数组,还是new Number等等。

这个时候就需要用到instanceof。

Instanceof运算符的第一个变量是一个对象,暂时称为A;第二个变量一般是一个函数,暂时称为B。

Instanceof的判断队则是:沿着A的__proto__这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。

notice
一条线一条线挨着分析
instanceof表示的就是一种继承关系,或者原型链的结构

继承

javascript中的继承是通过原型链来体现的

访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链。

在实际应用中如何区分一个属性到底是基本的还是从原型中找到的呢?hasOwnProperty,特别是在for…in…循环中

由于所有的对象的原型链都会找到Object.prototype,因此所有的对象都会有Object.prototype的方法。这就是所谓的“继承”。

每个函数都有call,apply方法,都有length,arguments,caller等属性。为什么每个函数都有?这肯定是“继承”的。函数由Function函数创建,因此继承的Function.prototype中的方法。

hasOwnProperty是Function.prototype继承自Object.prototype的方法。

原型的灵活性

在Java和C#中,你可以简单的理解class是一个模子,对象就是被这个模子压出来的一批一批月饼(中秋节刚过完)。压个啥样,就得是个啥样,不能随便动,动一动就坏了。

而在javascript中,就没有模子了,月饼被换成了面团,你可以捏成自己想要的样子。

对象或者函数,刚开始new出来之后,可能啥属性都没有。但是你可以这会儿加一个,过一会儿在加两个,非常灵活。

Object和Array的toString()方法不一样。肯定是Array.prototype.toString()方法做了修改

如果你要添加内置方法的原型属性,最好做一步判断,如果该属性不存在,则添加。如果本来就存在,就没必要再添加了。

执行上下文

在一段js代码拿过来真正一句一句运行之前,浏览器已经做了一些“准备工作”,其中就包括对变量的声明,而不是赋值。变量赋值是在赋值语句执行的时候进行的。

我们总结一下,在“准备工作”中完成了哪些工作:

变量、函数表达式——变量声明,默认赋值为undefined;
this——赋值;
函数声明——赋值;
这三种数据的准备情况我们称之为“执行上下文”或者“执行上下文环境”。

这个“代码段”其实分三种情况——全局代码,函数体,eval代码。

函数每被调用一次,都会产生一个新的执行上下文环境。

函数在定义的时候(不是调用的时候),就已经确定了函数体内部自由变量的作用域。

给执行上下文环境下一个通俗的定义——在执行代码之前,把将要用到的所有的变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。

this

this的取值,分四种情况

在函数中this到底取何值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了。

因为this的取值是执行上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91362.html

相关文章

  • 面向对象的 JavaScript

    摘要:是完全的面向对象语言,它们通过类的形式组织函数和变量,使之不能脱离对象存在。而在基于原型的面向对象方式中,对象则是依靠构造器利用原型构造出来的。 JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来人们对这一门语言的误解,即认为 JavaScript 不是一门面向对象的语言,或者只是部分具备一些面向对象的特征。本文将回归面向对象本意,从对语言感悟的角度阐述为什...

    novo 评论0 收藏0
  • JavaScript面向对象核心知识归纳

    摘要:一面向对象概念面向对象就是使用对象。因此在构造函数中表示刚刚创建出来的对象。在构造函数中利用对象的动态特性为其对象添加成员。 一、面向对象 1.1 概念 面向对象就是使用对象。面向对象开发就是使用对象开发。 面向过程就是用过程的方式进行开发。面向对象是对面向过程的封装。 1.2 三大特性 抽象性所谓的抽象性就是:如果需要一个对象描述数据,需要抽取这个对象的核心数据 提出需要的核心...

    TalkingData 评论0 收藏0
  • JavaScript 基本功--面试宝典

    摘要:示例构造函数继承实例对象其次,我们还可以使用中的新语法等关键字来实现继承。对象的属性是该对象的构造函数的属性。基于上边构造函数继承代码作用域与命名空间如果了解的用法,那么就应该只要有块级作用域和函数作用域。 JavaScript数据类型 JavaScript中有哪些基本数据类型 undefined、null、number、string、boolean、symbol(es6中新增)为啥没...

    Coly 评论0 收藏0
  • 对Javascript 类、原型继承理解

    摘要:因为我们用这个函数来构造对象,所以我们也把称作构造函数。所以通过定义构造函数,就相当于定义了一个类,通过关键字,即可生成一个实例化的对象。 一、序言   和其他面向对象的语言(如Java)不同,Javascript语言对类的实现和继承的实现没有标准的定义,而是将这些交给了程序员,让程序员更加灵活地(当然刚开始也更加头疼)去定义类,实现继承。(以下不讨论ES6中利用class、exten...

    sevi_stuo 评论0 收藏0
  • #yyds干货盘点# 前端基础知识面试集锦3

    摘要:当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体如何实现继承构造继承原型继承实例继承拷贝继承原型机制或和方法去实现较简单,建议使用构造函数与原型混合方式。它是基于的一个子集。 JavaScript介绍js的基本数据类型。Undefined、Null、Boolean、Number、Stri...

    番茄西红柿 评论0 收藏2637

发表评论

0条评论

xuexiangjys

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<