来来来,JavaScript核心基础语句送给你们
学JS你不会DOM算真的学会了吗?
对JavaScript中的 事件 进行疯狂 处理
用BOM来实现轮播图效果
我们来实现创建JavaScript中的自定义对象
JS中构造函数的原型prototype
还不明白JS中的内置对象吗? 快来这里!
JavaScript中数据如何存储在客户端?带你看看Cookie和WebStorage
在构造函数中有一个属性叫prototype
语法:
构造函数.prototype.属性名 = 值;
构造函数.prototype.方法名 = function(){定义方法体};
访问对象属性的查找顺序:
作用:
<script>
//定义一个构造函数Student
function Student(name,age){
this.name = name; //实例属性,每个实例都具有一个独立的该属性
this.age = age;
this.show = funciton(){
//实例方法,每个对象都具有一个独立的该方法
console.log('我叫'+this.name+'年龄'+this.age);
}
/*
this.sayhello = function(){
console.log('您好');
}
this.sayDoodbye = function(){
console.log('再见');
}
*/
}
//构造函数中存在一个名为prototype的属性
//console.log(Student.prototype);
//通过为构造函数的prototype添加属性和方法,从而让所有该构造函数创建的对象都能共享这些属性和方法
this.sayhello = function(){
//原型方法
console.log('您好');
}
this.sayDoodbye = function(){
console.log('再见');
}
Student.prototype.class = '三年级二班'; //原型属性,所有对象共享的原型对象class
//创建对象
var stu1 = new Student('tom',26);
stu1.class = '三年级一班'; //为stu1添加一个实例对象class
console.log(stu1.name,stu1.age,stu1.calss);
stu1.show();
stu1.sayhello();
stu1.sayGoodbye();
var stu2 = new Student('alice',22);
console.log(stu2.name,stu2.age,stu.class);
stu2.show();
stu2.sayhello();
stu2.sayGoodbye();
//stu1.sayhello()、sayGoodbye()和stu2.sayhello()、sayGoodbye()分别使用不同的内存空间,都要占用资源,但其内容完全相同,为了节省内存空间,希望能够公用。
console.log(stu1 === stu2);
console.log(stu1.name === stu2.name);
console.log(stu1.show === stu2.show);
console.log(stu1.sayhello === stu2.sayhello );
console.log(stu1.sayGoodbye === stu2.sayGoodbye);
//扩展Array
var names = new Array('tom','jack','alice','mike','alex');
//names.sort();
//names.reverse();
//names.join('-');
//为Array类型添加显得功能(属性或方法)
Array.prototype.sortReverseJoin = function(){
console.log(this); //this表示当前对象,即将来要操作的数组
this.sort();
this.reverse();
var str = this.join('-');
console.log(str);
}
console.log(Array.prototype);
var hobbies = ['eat','sleep','play','study'];
names.sortReverseJoin();
bobbies.sortReverseJoin();
</script>
prototype是一个隐藏属性,于是为每个对象那个提供一个叫__proto__的属性
<script>
function Student(name){
this.name = name;
this.show = function(){
console.log('我叫'+this.name);
}
}
Student.prototype.sayhello = function(){
console.log('你好');
}
//构造函数的prototype属性
//console.log(Student.prototype);
//stu会自动链接到其构造函数的prototype属性上
var stu = new Student('tom');
//stu.sayhello();
console.log(stu);
console.log(stu.__proto__); //__proto__是对象的属性,是站在对象的角度,来讨论其原型对象
console.log(Student.prototype); //prototype是构造函数的属性,是站在构造函数的角度,来讨论其原型对象
console.log(stu.__proto__ === Student.prototype);
//由于__proto__是非标准属性,因此一般不建议使用
//stu.__proto__.sayhello();
stu.sayhello();
</script>
判断数据的类型:
使用typeof
可以判断任意变量的类型
判断对象的类型时总是返回object
使用instanceof
只能判断对象是否为某种类型,需要指定判断的目标数据类型,无法获取对象的类型名称
语法:对象 instanceof 数据类型
,返回boolean值
获取对象的类型:
var stu = new Student() ------->Student类型
var p = new Person() ------->Person类型
var nums = new Array() -------->Array类型
var obj = new Object() ------->Object类型
function Student(){
};
function Teacher(){
};
var obj1 = new Object();
var obj2 = new Array();
var obj3 = new Student();
var obj4 = new Teacher();
//typeof只能判断简单的数据类型,判断对象的类型时总是返回object
//console.log(typeof obj1);
//console.log(typeof obj2);
//console.log(typeof obj3);
//console.log(typeof obj4);
//instanceof用来判断对象的类型,判断对象是否为某种类型,返回boolean
console.log(obj1 instanceof Object);
console.log(obj2 instanceof Array);
console.log(obj3 instanceof Student);
console.log(obj4 instanceof Teacher);
//结论:构造函数的名称就是对象的类型名
每个对象都有一个constructor属性,该属性描述的就是其构造函数。
对象的constructor属性是原型对象提供的,因为每个对象都链接到其原型对象上。
如果想要获取一个对象的构造函数的名字,我们就可以使用constructor属性和name属性
//运用上面例子中创建的对象
console.log(obj3.constructor.name); //通过构造函数的name属性,获取构造函数的名称
作用:以某个对象的身份来调用另一个对象的方法
区别:传参的方式不同
第一个参数是相同的,都是表示由该对象来调用执行
后面的参数不同
call是逐个传参,后面参数可以有多个,逗号隔开
apply是以数组形式传参,后面参数只能有一个,会自动拆分为多个元素传入
//定义一个对象,包含属性和方法
var stu = {
name:'tom',
age:18,
study:function(){
console.log('我叫'+this.name+',年龄:'this.age);
}
}
//stu.study(); //调用对象的方法
function run(){
console.log('跑步');
}
run(); //window直接调用函数
/**
* 如果stu想要调用run()方法,怎么办?
*/
//方式一:为stu添加run()方法,永久添加
stu.run = run; //为stu添加run()方法,指向run()函数
stu.run();
//方式二:只想临时调用(注意这里的写法)
run.call(stu); //以stu对象的身份来调用run()函数
run.apply(stu); //此处两个函数能实现相同的功能
//this的转变
window.run(); //直接调用,此时的this表示window
run.call(stu); //对象临时调用,此时的this表示调用的对象,即stu,称为对象冒充
/**
* call()和apply()的区别
*/
function calc(a,b,c){
console.log(a+b+c);
}
calc.call(stu,1,2,3); //逐个传参
calc.apply(stu,[1,2,3]); //数组形式传参,只能传一个参数
/**
* 应用场景
*/
//在stu对象中添加一个属性
stu.sex = 'male'; //直接添加
Array.prototype.push.call(stu,'male'); //通过push()方法添加
Array.prototype.push.call(stu,'hobby');
//Object.prototype.toString()方法,用来判断值的类型
console.log(Object.prototype.toString.call('hello'));
console.log(Object.prototype.toString.call(true));
console.log(Object.prototype.toString.call(undefined));
console.log(Object.prototype.toString.call(null));
console.log(Object.prototype.toString.call(new Array()));
JS实现继承的三种方式:
对象冒充继承,也称为构造继承
核心:使用call,以对象冒充的形式调用父类的构造函数,相当于是复制父类的实例属性给子类
缺点:只能继承父类构造函数中的属性和方法,无法继承原型中的属性和方法
原型链继承
核心:使用prototype,将父类的实例作为子类的原型
缺点:创建子类实例时,无法向父类构造函数传参,导致继承的父类属性没有值
组合继承
对象冒充+原型链
function Person(name,age){
this.name = name;
this.age = age;
this.run = function(){
console.log('跑步');
}
}
Person.prototype.sex = 'male';
Person.prototype.show = function(){
console.log('我叫'+this.name+',年龄:'+this.age+',性别:'+this.sex);
}
/**
* 方式1:对象冒充继承,也称为构造函数
*/
function Student(name,age){
Person.call(this,name,age); //此处Person中的this指向的是将来创建的Student对象
}
var stu = new Student('tom',20);
//可以继承父类构造函数中的属性和方法
console.log(stu.name,stu.age);
stu.run();
//无法继承父类原型中的属性和方法
console.log(stu.sex);
stu.show;
/**
* 方式2:原型链继承
*/
function Student(name,age){
}
Student.prototype = new Person(); //将Student原型链指向Person对象,从而继承Person
console.log(Student.prototype);
var stu = new Student('tom',20);
console.log(stu.name,stu.age); //name和age属性都是undefined,无法获得父类对象的属性
stu.run();
console.log(stu.sex);
stu.show();
/**
* 方式3:组合继承(对象冒充+原型链)
*/
function Student(name,age){
Person.call(this,name,age); //对象冒充
}
//(1)调用两次父类的构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了,所以性能稍差一点)
Student.prototype = new Person();
//(2)将Student原型指向Person原型
Student.prototype = Person.prototype;
var stu = new Student('tom',20);
console.log(stu);
</script>
任何对象都有其原型对象,原型对象也有原型对象,对象的原型对象一直往上找,直到null为止。
在这一过程中,有一个Object类型的对象,它就是Object prototype位于顶层。
/**
* nums对象的原型链
* nums——>Array.prototype——>Object.prototype——>null
* nums.__porto__与Array.prototype是同样的
*/
var nums = new Arrray(12,43,5,3,8);
nums.push(24);
nums.reverse();
console.log(nums);
/**
* stu对象的原型链结构
* stu——>Student.prototype——>Object.prototype——>null
* stu.__prototype__与Student.prototype是同样的
*/
function Student(name){
this.name = name;
}
Student.prototype.sex = 'male';
var stu = new Student('tom');
console.log(stu);
//Object的原型链结构
var o1 = new Object();
console.log(o1); //创建对象
console.log(Object.prototype); //对象的原型,站在构造函数的角度
console.log(o1.__proto__); //对象的原型,站在对象的角度
console.log(Object.prototype.constructor); //构造函数