摘要:因为构造函数调用会将一个全新的对象作为变量的值,并隐式返回这个新对象作为调用的结果。一个开发者熟知的解决方案是,在调用函数前先判断函数的接收者是否为当前函数的实例。注意,上面二种解决方案都使用了操作符来判断对象的实例。
在JavaScript中函数作为对象的属性使用时,我们称其为方法调用;如果函数使用new操作符来调用时,我们称其为构造函数。
在涉及到构造函数时,通常绕不开关于this的讨论。因为构造函数调用会将一个全新的对象作为this变量的值,并隐式返回这个新对象作为调用的结果。
在使用构造函数时,如果调用者忘记使用new关健字,那么函数的接收者将是全局对象。
function Person(name, age) { this.name = name; this.age = age; } // 使用`new`调用 var jenemy = new Person("jenemy", 18); console.log(window.age); // undefined // 不使用 var jenemy = Person("jenemy", 18); console.log(window.age); // 18
不使用new调用构造函数的结果是我们无意间创建了全局变量name和age,如果这些全局变量已经存在则会被修改。
一个开发者熟知的解决方案是,在调用函数前先判断函数的接收者是否为当前函数的实例。
function Person(name, age) { if (!(this instanceof Person)) { return new Person(name, age); } this.name = name; this.age = age; }
这种模式的一个缺点是需要额外的函数调用,在性能上代价有点高。一种更为有效的方式是使用ES5的Object.create()函数。
function Person(name, age) { var self = this instanceof Person ? this : Object.create(Person.prototype); self.name = name; self.age = age; return self; }
注意,上面二种解决方案都使用了instance操作符来判断对象的实例。如果看过我写的《javascript判断一个对象是否为数组》文章,会发现instanceof操作符并不可靠。上面的示例,稍作修改:
function Person(name, age) { this.name = name; this.age = age; } Object.defineProperty(Person, Symbol.hasInstance, { value(v) { return false; } }) var wu = new Person("jenemy", 18); console.log(wu instanceof Person); // false
如果没有修改Person对象内建的Symbol.hasInstance方法,上面的结果很显然应该在控制台输出true。为了解决函数调用这种模棱两可的问题,ES6提供了元属性new.target,当调用函数的[[Construct]]方法时,new.target被赋值为new操作的目标,通常为新创建对象的实例。
function Person(name, age) { if (!new.target) { throw "Peron must called with new"; } this.name = name; this.age = age; } var wu = Person("jenemy", 18); // Uncaught Peron must called with new
需要注意的是在函数外使用new.target会报语法错误。同时,它不受对象的Symbol.hasInstance方法被修改的影响。所以如果是在ES6环境,使用new.target是最可靠的解决方案。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/88521.html
摘要:注意基本变量类型不是对象类型,只有基本包装类型才是对象类型。至于显示的原型,在里用属性表示,这个是原型继承的基础知识,在这里就不在叙述了。 前言 如果你要开发一个复杂的产品,那么肯定少不了使用面向对象机制,当然也避不开 Javascript 里面的继承,instanceof 运算符是原生 Javascript 语言中用来判断实例继承的操作符。所以我们有必要深入理解该运算符! inst...
摘要:三种使用构造函数创建对象的方法和的作用都是在某个特殊对象的作用域中调用函数。这种方式还支持向构造函数传递参数。叫法上把函数叫做构造函数,其他无区别适用情境可以在特殊的情况下用来为对象创建构造函数。 一、工厂模式 工厂模式:使用字面量和object构造函数会有很多重复代码,在此基础上改进showImg(https://segmentfault.com/img/bVbmKxb?w=456&...
摘要:检测函数从技术上讲,中的函数是引用类型,同样存在构造函数,每个函数都是其实例,比如不好的写法然而,这个方法亦不能跨帧使用,因为每个帧都有各自的构造函数,好在运算符也是可以用于函数的,返回。 上周写过一篇读书笔记《编写可维护的JavaScript》之编程实践,其中 第8章 避免『空比较』是博主在工作中遇坑较多的雷区,所以特此把该章节重新整理分享,希望大家不再坑队友(>﹏<)。 在 Jav...
摘要:这样每个实例独享自己的属性,并和其他同类型的实例共享方法构造函数原型以上这种方式定义的类型,可以通过来判断一个实例是否是类型的实际上是通过实例的原型链来判断一个对象是否某个类型的实例的,具体的细节后面会详细介绍。 JavaScript面向对象编程 如何定义自定义类型 首先需要明确,JavaScript并不是传统意义上的OO语言,它并没有class的概念, 而是包含了另一套异常强大的...
摘要:和的作用一样,区别在于写法语法对象对象作用判断对象是否在对象的原型链上语法对象构造函数作用判断构造函数的属性是否在对象的原型链上,如果在,就返回属性是否可枚举用于检查给定的属性是否能够使用语句。 ## javascript对象原型成员详解 ## ECMAScript 中的对象就是一组数据和功能的集合,对象可以通过 new 操作符后跟要创建的对象名称来...
阅读 2413·2021-09-27 13:36
阅读 2148·2019-08-29 18:47
阅读 2071·2019-08-29 15:21
阅读 1373·2019-08-29 11:14
阅读 1954·2019-08-28 18:29
阅读 1571·2019-08-28 18:04
阅读 550·2019-08-26 13:58
阅读 3148·2019-08-26 12:12