摘要:如果按照字面意思来理解,那么就是通过调用构造函数而创建的那个对象实例的原型对象。
创建对象方法
Object构造函数
对象字面量表示
工厂模式
构造函数模式
原型模式
构造函数模式与原型模式结合
动态原型模式
寄生构造函数模式
一、Object实例创建var person1 = new Object(); person1.name = "bob"; person1.age = "22"; person1.job = "frontend"; person1.sayName = function () { console.log(this.name); } person1.sayName(); // bob console.log(person1.age); // 22二、对象字面量表示
var person2 = { name: "bob", age: 22, job: "frontend", sayName: function () { console.log(this.name); } } person2.sayName(); // bob三、工厂模式
function createPerson(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function () { console.log(this.name); }; return o; } var person1 = createPerson("bob", 22, "frontend"); var person2 = createPerson("lynn", 22, "doctor"); console.log(person1.name); // bob console.log(person2.name); // lynn
优点:函数封装创建对象,无需写重复创建对象的代码
缺点:没有解决对象识别的问题(怎么样知道一个对象类型)
四、构造函数模式function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { console.log(this.name); } /** * 与声明函数在逻辑上是等价的 this.sayName = new Function("console.log(this.name)"); */ } var person1 = new Person("bob", 22, "frontend"); var person2 = new Person("lynn", 22, "doctor"); console.log(person1.name); // bob console.log(person2.name); // lynn
没有显式地创建对象
直接将属性和方法赋给了this对象
没有return语句
每个方法都要在每个实例上重新创建一遍
创建新的对象
将构造函数的作用域赋给新对象,因此this就指向了这个对象
执行构造函数的代码,为这个对象添加对象属性和方法
返回新的对象
person1和person2分别保存着Person的一个不同的实例。这两个对象都有一个constructor(构造函数)属性,该属性指向Person
console.log(person1.constructor === Person); // true console.log(person2.constructor === Person); // true
对象的constructor属性最初是用来标识对象类型的。但是,提到检测对象类型,还是instanceof操作符要更可靠一些
console.log(person1 instanceof Object); // true console.log(person1 instanceof Person); // true console.log(person2 instanceof Object); // true console.log(person2 instanceof Person); // true
我们在这个例子中创建的所有对象既是Object的实例,同时也是Person的实例,这一点通过instanceof操作符可以得到验证,创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型
// 当作构造函数使用 var person = new Person("bob", 22, "frontend"); person.sayName(); //"Nicholas" // 作为普通函数调用 Person("lynn", 22, "doctor"); // 添加到window window.sayName(); //"Greg" // 在另一个对象的作用域中调用 var o = new Object(); Person.call(o, "Kristen", 25, "Nurse"); o.sayName(); //"Kristen"
构造函数创建的对象方法,实际上执行多次函数创建,会导致不同的作用域链和标识符解析,如:
console.log(person1.sayName == person2.sayName); //false
创建两个完成同样任务的Function实例的确没有必要;况且有this对象在,根本不用在执行代码前就把函数绑定到特定对象上面。因此,大可像下面这样,通过把函数定义转移到构造函数外部来解决这个问题。
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = sayName; } // 把sayName函数抽离出外部函数 function sayName() { console.log(this.name); }
存在问题:
所有被新创建出来的对象,都会指向全局作用域的sayName函数,如果定义N个方法,那么就要定义N个全局的方法,这就造成了封装性的瓶颈,不过可以使用原型模式来解决
五、原型模式function Person() { } Person.prototype.name = "bob"; Person.prototype.age = 22; Person.prototype.job = "frontend"; Person.prototype.sayName = function () { return this.name } var person1 = new Person(); console.log(person1.name); // bob console.log(person1.age); // 22 console.log(person1.job); // frontend console.log(person1.sayName()); // bob console.log(person1.sayName === person2.sayName); // true
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。如果按照字面意思来理解,那么prototype就是通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。
六、组合使用构造函数模式和原型模式function Person(name, age, obj) { this.name = name; this.age = age; this.obj = obj; } Person.prototype = { constructor: Person, sayName: function () { console.log(this.name); } } var person1 = new Person("bob", 22, "frontend"); var person2 = new Person("lynn", 22, "doctor"); console.log(person1.name); // bob console.log(person2.name); // lynn console.log(person1.sayName === person2.sayName); // true七、动态原型模式
function Person(name, age, obj) { this.name = name; this.age = age; this.obj = obj; console.log("typeof this.sayName: ", typeof this.sayName); // 检测sayName 是不是一个函数 // 实际上只在当前第一次时候没有创建的时候在原型上添加sayName方法 if (typeof this.sayName != "function") { Person.prototype.sayName = function () { return this.name; } } } var person1 = new Person("bob", 22, "frontend"); var person2 = new Person("lynn", 22, "doctor"); console.log(person1.name); // bob console.log(person2.name); // lynn console.log(person1.sayName()); // bob console.log(person2.sayName()); // lynn console.log(person1.sayName === person2.sayName); // true八、寄生构造函数模式
function createPerson(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function () { console.log(this.name); }; return o; } var person1 = new createPerson("bob", 22, "frontend"); var person2 = new createPerson("lynn", 22, "doctor"); console.log(person1.name); // bob console.log(person2.name); // lynn
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/95937.html
摘要:原型式继承利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型。其中表示构造函数,一个类中只能有一个构造函数,有多个会报出错误如果没有显式指定构造方法,则会添加默认的方法,使用例子如下。 (关注福利,关注本公众号回复[资料]领取优质前端视频,包括Vue、React、Node源码和实战、面试指导)showImg(https://segmentfault.com/img/rem...
摘要:使用也有很长一段时间但是一直以来都没对其组件之间的通信做一个总结这次就借此总结一下。引用信息将会注册在父组件的对象上。 使用Vue也有很长一段时间,但是一直以来都没对其组件之间的通信做一个总结,这次就借此总结一下。 父子组件之间的通信 1)props和$emit 父组件通过props将数据下发给props,子组件通过$emit来触发自定义事件来通知父组件进行相应的操作 具体代码如下: ...
摘要:假定期望交换和的值序号实现方案中间变量备注按位操作符只适用类型只适用类型有脑洞先执行对象解构赋值推荐数组解构赋值简书首发转载请注明来自简书 假定let a = 1,b=10;期望交换a和b的值 序号 实现方案 中间变量? 备注 1 let c; c = a; a = b; b = c; ✅ 2 a ^= b; b ^=a; a ^=b MDN-按位操作符, 只适...
摘要:目标追踪首先,我们会大致介绍八种建立在上的目标跟踪算法。词典包含了种的目标追踪器行。它将目标追踪器的命令行参数字符串映射到实际的追踪器函数上。其中行里的目的是根据追踪器命令行参数以及从得来的相关重要信息。 虽然我们熟知的的质心追踪器表现得很好,但它需要我们在输入的视频上的每一帧运行一个目标探测器。对大多数环境来说,在每帧上进行检测非常耗费计算力。所以,我们想应用一种一次性的目标检测方法,然后...
阅读 2680·2021-10-11 10:57
阅读 1527·2021-09-26 09:55
阅读 1272·2021-09-06 15:11
阅读 3412·2021-08-26 14:16
阅读 621·2019-08-30 15:54
阅读 500·2019-08-30 12:43
阅读 3234·2019-08-29 16:18
阅读 2523·2019-08-23 16:14