1.原型方法和对象的检测问题
(1):isPortotypeOf():检测当前对象是否是基于对应构造函数创建出来的
function Student(name){
this.name=name
}
Student.prototype.show=function(){
console.log(this.name)
}
var s1=new Student("王一")
var t=Student.prototype.isPrototypeOf(s1)
console.log(t)
从代码中可以看到 s1对象是由Student这个函数而创建的对象,所以最后的输出的值是true
(2):判断属性方法
hasOwnProtperty()判断当前的属性和方法是否源于对象构造函数内部,也就是不在对象的原型数中输出的数据类型是boolean类型
function Student(name){
this.name=name
}
Student.prototype.show=function(){
console.log(this.name)
}
var s1=new Student("王一")
var t=s1.hasOwnPortperty("name")
console.log(t)
var s=s1.hasOwnPortperty("show")
console.log(s)
上面的代码中 t 输出的是true,因为name属性是在Student对象构造函数的内部而不在原型中。S输出的就是false,因为show方法是写在Student对象的原型中的。
in 判断当前对象是否具有对应属性和方法,(属性 in 对象)。只要该对象具有对应的属性和方法(不管这个方法和属性是在构造函数内部还是在原型中)
function Student(name){
this.name=name
}
Student.prototype.show=function(){
console.log(this.name)
}
var s1=new Student("王一")
var t="show" in s1
console.log(t)
var s="name" in s1
console.log(s)
上面代码中的t和S输出的都是true,因为这两个属性或方法都是Student这个对象所具有的。
2.面向对象编程的特点
(1).抽象性:都是从一个个对象开始分析 。(2).封装性:面向对象编程都是将属性和方法封装到对象里,方便后面的维护,二次开发。 (3).继承性:将对象的属性和方法进行传递,(如原型链,this的指向性问题)。 (4).多态性:js中还无法做到
封装性:属性分共有属性,私有属性。
共有属性:任何人在任何位置都可以任意得访问以及修改
私有属性:必须达到某些条件才能更改或者访问。(安全性比较高)
在js中我们用局部变量来模拟私有概念,通过get和set方法来实现私有属性的获取和设置
function Student(name,mail){
var mail=mail
this.name=name
this.getMail=function(user){
if(user.name==this.name){
return mail
}else{
return "权限不够"
}
}
this.setMail=function(num){
var reg=/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/
if(reg.test(num)){
mail=num
}else{
alert("格式错误")
}
}
}
var user={
name:"张三"
}
var s1=new Student("张三",182155483355)
console.log(s1.getMail(user))
s1.setMail("1985918706@qq.com")
console.log(s1.getMail(user))
我先是利用构造函数来创建了一个对象,在构造函数内部定义了一个变量mail,然后就是创建了一个get获取函数,里面加入了一些判断来模拟私有属性所需要的条件。接着有创建了一个set创建函数创建一个新的mail,里面也加入了一些判断。当我们调用get方法时,我们传入的参数的name属性必须和创建对象的name属性是一样的,不然时获取不到mail的。这样我们就模拟出了私有属性。而set方法也是要进行判断的,不然也是创建不了的。
改变this的指向性问题: 一般都采用call()和apply()方法来改变this的指向性,apply()和call()方法的作用是一样的都是改变this的指向性,在书写上会有点区别。
.call()第一个参数 改变的对象 后面参数传入方法对应的参数
function Student(name,age){
this.name=name
this.age=age
}
Student.prototype.show=function(){
console.log(this.name)
}
Student.prototype.abc=function(a,b,c){
console.log(this.name+a+b+c)
}
var s1=new Student("张三",20)
var s2=new Student("李四",25)
s1.show.call(s2)
s2.show.call(s1)
上面代码中s1调用输出函数时,本来他的this指向的就是s1,但是在我们加上了call()方法后,让this指向了s2,s1输出的结果就是 “李四” 。而后面的s2调用输出函数同样加上了call()方法,让this指向了s1,s2输出的结果是“张三”
.apply():第一个参数 改变的对象,后面的参数是放在一个数组里面的,和call方法的区别就在这
function Student(name,age){
this.name=name
this.age=age
}
Student.prototype.show=function(){
console.log(this.name)
}
Student.prototype.abc=function(a,b,c){
console.log(this.name+a+b+c)
}
var s1=new Student("张三",20)
var s2=new Student("李四",25)
s1.show.apply(s2)
s2.show.apply(s1)
s1.abc.apply(s2,[1,2,3])
apply()方法和call()在没有后续参数的情况下是没有去别的。但是再有参数的情况下,apply后面的参数是放在一个数组里面。call()是直接把参数放在参数列表中。
但是apply()方法有个用法,在我们创建一个数组数据后想要获取数组中的最大值。我们通常都是利用数组的遍历然后在比较大小。而apply()可以提供一个方法来获取最大值。
var arr=[1,3,4,5]
var result1=Math.max(arr)
var result2=Math.max.apply(null,arr)
console.log(result1)
console.log(result2)
result1的值为NaN,Math.max()是不支持数组的,它支持的类型有double,float,int,long四种类型,我们利用apply()来解析数组并进行传参,从而实现数据中最大值的查找。