资讯专栏INFORMATION COLUMN

漫谈js-原型

shuibo / 1446人阅读

摘要:原型链只看构造函数的原型对象和实例化出来的对象。既然构造函数本身是函数,那么和直接调用有什么区别答案揭晓只有通过调用构造函数才会走第二步,也就是原型的委托操作。

原型

相信js开发者都知道原型,原型链,但是很多人晕晕乎乎对此不知甚解。下面分享一下我的个人心得。

学习中的困惑

构造函数,原型,实例对象之间的关系是什么?

原型链是怎么继承的?

既然构造函数本身是函数,那么new和直接调用有什么区别,

解答 构造函数,原型,实例对象之间的关系是什么?

废话不说先上图

不需要管网上乱七八糟的各种原型链指向图,记住这个就行了。
除了各种指向以外,图中还包含这些信息:

"prototype"属性是函数独有的

__proto__才是实例的。当然,这个属性不建议使用。可以用Object.setPrototypeOfObject.getPrototypeOf

天真的我曾经以为原型是prototype,那原型链就是跟着prototype找...,实在是too young too simple啊。
这里一定要记住,原型链是沿着__proto__链找。

原型链是怎么继承的?

其实这个问题也可以是:当我们构建对象时,发生了什么。
举个简单例子:

function father(){
    this.name = "爸爸"
}
father.prototype.family = "爱的家"

var dad = new father();

这里进行了如下操作:

实例化一个空对象Object.create();

将father的[[prototype]]属性委托给father的原型。

指定上下文。即this为第一步实例化出来的空对象。

执行构造函数。

用代码模拟就是:

function _new(/* 构造函数 */ constructor, /* 构造函数参数 */ param1) {
  // 将 arguments 对象转为数组
  var args = [].slice.call(arguments);
  // 取出构造函数
  var constructor = args.shift();
  // 创建一个空对象,继承构造函数的 prototype 属性
  var context = Object.create(constructor.prototype);
  // 执行构造函数
  var result = constructor.apply(context, args);
  // 如果返回结果是对象,就直接返回,则返回 context 对象
  return (typeof result === "object" && result != null) ? result : context;
}

// 实例
var actor = _new(Person, "张三", 28);

记住一点,实例化对象以后,构造函数就没什么事了。原型链只看构造函数的原型对象和实例化出来的对象。
这里在说一点,关于,继承。现实中的继承就是你的东西给我了,我拿过来了。我可以使用,可以转让。但是js中真是这样吗?
一个很简单的问题,如果原型继承真是把原型中的属性拷过来那我每次自身找不到属性还要沿着原型链查找干嘛。
很显然,js中原型可不是二百五,他所谓的继承,只是给你使用权,不会给你转让权。
上面第二步中:将father的[[prototype]]属性委托给father的原型。我写的是委托。这样描述可能更准确。因为这里只是相当于给实例化对象一个指针,指向了原型对象。这其实也是下一个问题的答案。

既然构造函数本身是函数,那么new和直接调用有什么区别

答案揭晓:
只有通过new调用构造函数才会走第二步,也就是原型的委托操作。
那么怎么判断是否同new调用呢?

判断是否通多new调用函数

ES6函数内部可以使用new.target属性。如果当前函数是new命令调用,new.target指向当前函数,否则为undefined。
ES5

if(this instanceof Father){...}

ES6

//在函数外使用new.target是一个错误
typeof new.target !== "undefined"

这里再多扯一下typeof和instance。反正我以前是每次看了记住了,很久不用又忘了。。。。,看了这么多原型链的内容,再看看这个应该会映象深刻吧:

typeof :

用来判断值类型。如string/number/boolean,但如果判断引用类型,返回值就只有 object/function。所以无法进一步判断是object对象,还是数组,还是new Number等等。
注意:

undefined返回undefined。 
// 错误的写法
if (v) {
  // ...
}
// ReferenceError: v is not defined

// 正确的写法
if (typeof v === "undefined") {
  // ...
}
instanceof :

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

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

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

相关文章

  • 漫谈javascript函数式编程

    摘要:高阶函数不是的所特有的,其他编程语言也有。高阶函数面向切面编程面向切面编程这种思想在开发中比较常见,主要就是将一些与核心业务无关的功能抽离出来,比如异常处理,日志统计等。 javascript的函数式语言特性 我们知道JavaScript使一门面向对象的编程语言,但这门语言同时拥有很多函数式语言的特性。 JavaScript的设计者在设计最初就参考了LISP方言之一的Scheme,引入...

    liaorio 评论0 收藏0
  • 漫谈前端之路

    摘要:那么的学习就相对来说很自由了,可以跟着网址过一遍标签,网上也有很多其它网站做这个的,像菜鸟教程慕课网视频之类的都可以用等熟练了就可以去国外看看一些前端的新技术,像国际,最大的程序员问答网站。 前言 前端之路何其漫漫~     说明:本篇文章原是写给学弟学妹的,但想来花的功夫确实不少,就把此篇文章当做自己的一个阶段性总结文章了,会保持长期更新。 HTML     总的来说HTML并不难,...

    qujian 评论0 收藏0
  • 漫谈前端之路

    摘要:那么的学习就相对来说很自由了,可以跟着网址过一遍标签,网上也有很多其它网站做这个的,像菜鸟教程慕课网视频之类的都可以用等熟练了就可以去国外看看一些前端的新技术,像国际,最大的程序员问答网站。 前言 前端之路何其漫漫~     说明:本篇文章原是写给学弟学妹的,但想来花的功夫确实不少,就把此篇文章当做自己的一个阶段性总结文章了,会保持长期更新。 HTML     总的来说HTML并不难,...

    番茄西红柿 评论0 收藏0
  • 漫谈前端之路

    摘要:那么的学习就相对来说很自由了,可以跟着网址过一遍标签,网上也有很多其它网站做这个的,像菜鸟教程慕课网视频之类的都可以用等熟练了就可以去国外看看一些前端的新技术,像国际,最大的程序员问答网站。 前言 前端之路何其漫漫~     说明:本篇文章原是写给学弟学妹的,但想来花的功夫确实不少,就把此篇文章当做自己的一个阶段性总结文章了,会保持长期更新。 HTML     总的来说HTML并不难,...

    BakerJ 评论0 收藏0
  • 漫谈前端之路

    摘要:那么的学习就相对来说很自由了,可以跟着网址过一遍标签,网上也有很多其它网站做这个的,像菜鸟教程慕课网视频之类的都可以用等熟练了就可以去国外看看一些前端的新技术,像国际,最大的程序员问答网站。 前言 前端之路何其漫漫~     说明:本篇文章原是写给学弟学妹的,但想来花的功夫确实不少,就把此篇文章当做自己的一个阶段性总结文章了,会保持长期更新。 HTML     总的来说HTML并不难,...

    RdouTyping 评论0 收藏0

发表评论

0条评论

shuibo

|高级讲师

TA的文章

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