如何选择网站建设案例,免费在线做网站,免费注册淘宝店铺,在自己网站上做销售在工商要办什么手续ES5对象特性
对象和函数的原型
JS中每一个对象都有一个特殊的内置属性#xff0c;这个特殊的对象可以指向其他的对象
我们通过引用对象的属性key来获取一个value时#xff0c;它会触发 Get 的操作首先检查该对象是否有对应的属性#xff0c;如果有的话就使用对象内的如果…ES5对象特性
对象和函数的原型
JS中每一个对象都有一个特殊的内置属性这个特殊的对象可以指向其他的对象
我们通过引用对象的属性key来获取一个value时它会触发 Get 的操作首先检查该对象是否有对应的属性如果有的话就使用对象内的如果对象中没有属性那么会访问对象的prototype每一个对象都有一个原型属性
使用方式有两种
通过对象的 _proto_ 属性可以获取到浏览器自己添加的存在一定的兼容性问题)通过 Object.getPrototypeOf 方法可以获取 prototype属性是函数特有的属性 我们的对象只能通过Object.getPrototypeOf来查看原型。 var obj {}function foo() {}console.log(foo.prototype);当我们这个对象有对多个共同值的时候可以把相同的东西当如原型里这样每次创建这个对象的时候就可以直接调用而不是重新创建。 function Student(name, age) {this.name namethis.age age// 如果我们每个对象都创建那么这两个方法会出现很多的冗余// this.running function () {// console.log(this.name running);// }// this.eating function () {// console.log(this.name eating);// }}Student.prototype.running function () {console.log(this.name running);}Student.prototype.eating function () {console.log(this.name eating);}var stu1 Student(jjj, 12)var stu2 Student(hhh, 18)Constructor属性
原型对象上面是有一个属性的constructor默认情况下原型都会有一个叫constructor指向当前的对象 function Person() { }var PersonProtype Person.prototypeconsole.log(PersonProtype);console.log(PersonProtype.constructor);console.log(PersonProtype.constructor Person);原型对象是可以重写的当我们需要给原型添加更多的属性的时候一般我们会选择重写原型对象
我们也可以改变原型对象中constructor的指向的使用
//改变指向对象Person.prototype{constructor:Person}
//修改枚举类型Object.defineProperty(Person.prototype,constructor,{enumerable:false})这里要注意的是原生的constructor是不可枚举的但是修改constructor的时候会让constructor的特性被设置为true这个时候需要修改一下对象默认属性设置
创建对象的内存表现 如果我们向对象加入属性在之后的变化: 多种继承方式 继承 面向对象有三大特性封装、继承、多态
封装我们前面将属性和方法封装到一个类中可以称之为封装的过程继承继承是面向对象中非常重要的不仅仅可以减少重复代码的数量也是多态前提纯面向对象中多态不同的对象在执行时表现出不同的形态
这里主要将JS中的继承在了解继承之前我们需要了解JS中的原型链机制这个是之后理解的关键
原型链
在js中我们不断的获取原型对象原型链最顶层的原型对象就是Object的原型对象 [Object: null prototype] {}这种提示一般有两个情况
该对象有原型且这个原型的属性指向null或者最顶层了这个对象有很多的默认属性方法 psObject是所有类的父类 我们也可以对原型链做一些自定义操作比如这样 var obj {}obj.__proto__ {}obj.__proto__.__proto__ {}obj.__proto__.__proto__.__proto__ {name: 小冷}原型链实现继承 function Person(){this.name l
}var p new Person()
stu.prototype p
//name l
stu.prototype.studying function(){console.log(this.namestudying)
} 我们可以通过赋值原型的形式来实现继承但是有一些弊端
直接打印对象是看不到属性的这个属性会被多个对象共享如果是引用类型就会造成问题不能给父类传递参数没法定制化
借用构造函数继承
为了解决原型链继承中存在的问题constructor stealing应运而生 借用继承的做法非常简单在子类型构造函数的内部调用父类型构造函数
因为函数可以任意调用因此通过apply和call也可以再新创建的对象上实行构造函数 function Person(name, age, height, address) {this.name namethis.age agethis.height heightthis.address address}function Student(name, age, height, address, sno, score) {Person.call(this,name, age, height, address)this.sno snothis.score score}可以使用父类的构造函数来实现创造解决之前原型链的问题 在ES6之前一直是保持的这个方式但是这个继承方式依然不是很完美
无论在什么情况下都会调用两次父类构造函数。 一次是创建子类原型一次是构造函数所有的子类都会有两份父类的属性
继承最终方案
在继续的发展中, JSON的创立者道格拉斯 提到了新的继承方法这也是目前es5 阶段最合适的继承方案 寄生组合继承
结合原型类继承和工厂模式创建一个封装继承过程的函数在这个函数的内部来增强对象最后将这个对象返回 function Person(name, age, height, address) {this.name namethis.age agethis.height heightthis.address address}Person.prototype.running function () {console.log(this.name running);}function Student(name, age, height, address, sno, score) {Person.call(this, name, age, height, address)this.sno snothis.score score}// 原型继承var obj Object.create(Person.prototype)console.log(obj.__proto__ Person.prototype);Student.prototype obj// 上到真是环境 会封装用 为了兼容性可以多一个创造类的方法function object(o){function F(){}F.prototype oreturn new F()}function inherit(Subtype, Supertype) {Subtype.prototype object(Supertype.prototype)// 需要构造方法Object.defineProperty(Subtype, constructor, {enumerable: false,configurable: this,writable: true,value: Subtype})}inherit(Student, Person)Student.prototype.eating function () {console.log(this.name eating);}var stu new Student(小明);stu.eating()
对象方法补充
hasOwnProperty 对象是否有某一个属于自己的属性
in/for in 操作符 判断某个属性是否在对象或者对象的原型上
instanceof 用于检测构造函数的原型是否出现在某个实例对象的圆形脸上
isPrototypeOf用于检测某个对象是否出现在某个实例对象的原型链上