JavaScript 中的万物皆对象:字符串、数值、数组、函数...
对象只是带有属性和方法的特殊数据类型:
Oobject类型的创建方法
1.使用new运算符
var obj = new Object(); // 或者省略new var obj = Object();
obj.name = "张三";
obj.age = 18;
2.使用字面量方式创建,键值对方式:k: v
var obj0 = {
name: "张三",
age: 18
};
// 或者属性字段用字符串形式:
obj1 = {
"name": "张三",
"age": 18
};
// 也可以用传统的赋值方式:
var obj2 = {};
obj2.name = " 张三";
obj2.age = 18;
3.给对象创建方法
var obj = {
run: function() {
return '正在奔跑';
}
}
构造函数
构造函数:通常使用构造函数代表类
function Animal(name, age) {
this.name = name; // this指的是使用new关键字,调用Animal所创建的对象
this.age = age;
this.show = function() {
console.log(this.name + ',' + this.age);
};
};
var animal1 = new Animal('熊猫', 2);
var animal2 = new Animal('东北虎', 3);
animal1.show(); // 熊猫, 2
animal2.show(); // 东北虎, 3
image.png
其实在js中并没有类的概念,但是通常我们认为构造函数就是类。
上面的Animal就是类,animal1和animal2是对象,也是Animal的实例
类是对象的抽象
对象是类的具体
注意
- 在Animal使用new关键字创建的过程中,内部会自动创建一个对象;
- 然后把this这个指针指向创建的这个对象;
- 执行完代码后,还会返回这个对象;
原型对象
prototype:原型
function Box() { // 构造函数
};
Box.prototype.name = "虞姬";
Box.prototype.age = "18";
Box.prototype.show = function() {
console.log(this.name + ',' + this.age);
};
var box = new Box(); // 实例
console.log(box.name); // 虞姬
console.log(box.age); // 18
console.log(box.show); // 虞姬, 18
- constructor: 原型对象prototype的属性,指向当前原型所属的构造函数,即:
console.log(Box.prototype.constructor === Box); // true
image.png
- _ _ proto _ _属性:实例对象指向原型对象的一个指针,它的作用是指向构造函数的原型,即
console.log(box.__proto__ === Box.prototype); // true
console.log(box.__proto__.name); // 虞姬
image.png
- isPrototype(): 用来判断某个对象是否指向该原型对象的构造函数
1.查找实例对象是否存在该属性,如果存在则返回该属性的值;
2.如果不存在,则查找原型对象中是否存在,若存在,则返回该属性的值;
3.如果都不存在,则返回underfine。
console.log(Box.prototype.isPrototype(box)); // true
console.log(Box.prototype.isPrototype(box1)); // underfine
- hasOwnPrototype(): 用来判断该实例对象中是否含有该属性
1.存在,则返回true;
2.不存在,则返回false;
console.log(box.hasOwnPrototype(name)); // true
console.log(box.hasOwnPrototype(type)); // false
- in操作符:用于判断属性是否存在实例对象或者原型对象
首先会先判断当前实例对象中是否存在该属性,若存在,则返回true;若不存在,则会继续在原型对象中查找该属性,若存在,则返回true;若不存在,则继续往原型链的顶端Object.prototype中找,如果都没有就会返回false。
console.log("name" in box); // true
console.log("type" in box); // false
-
原型链
所有的函数对象都继承自原始函数对象;Function比较特殊,他的原型对象也就是原始函数对象;所以我们往往用Function.prototype表示原始函数对象;而原始函数对象又继承自原始对象。 image.png
- 封装:把部分属性和方法封装起来,不提供给外界使用
// 工厂模式创建
function createObject(_name, _age) {
var obj = new Object(); // 创建对象
obj.name = _name;
obj.age = _age;
obj.show = function() {
console.log(this.name + ',' + this.age);
};
return obj;
}
var person1 = createObject('Jacky', 18);
var person2 = createObject('喵喵', 20);
person1.show(); // Jacky, 18
person2.show(); // 喵喵,20
- 继承:可以把原有对象(父类)的属性和方法,复制给一个新的对象,新的对象还可以拥有自己的属性和方法
1.原型链继承
2.对象冒充,call和apply继承
对象.call(新this对象,实参1,实参2,实参3.....)
对象.apply(新this对象,[实参1,实参2,实参3.....])
function Cat() { // 父类
this.fur = "有软毛";
this.eat = function() {
console.log("喜欢吃鱼");
};
this.call = functiong() {
consoloe.log("喵~");
}
};
function GarfriendCat() {
this.galssess = "戴墨镜"; // 新增自己的属性
this.talk = function() { // 新增自己的方法
console,log("会说话");
};
this.eat = function() { // 重写父类的eat方法
console.log("只吃肉!");
}
};
GarfriendCat.prototype = new Cat(); // 使用原型链来实现继承。
// 对象冒充: 借用构造函数Cat,用this冒充Cat
function Person(_name, _age) {
this.name = _name;
this.age = _age;
}
// call
function CallCopy(_name, _age, _gender) {
Person.call(this, _name, _age);
this.gender = _gender;
} ;
var callCopy = new CallCopy('Jacky', 18, '男');
console.log(callCopy.name, callCopy.age, callCopy.gender); // Jacky 18 男
// apply
function ApplyCopy(_name, _age, _gender) {
Person.apply(this, [_name, _age]);
this.gender = _gender;
} ;
var applyCopy = new ApplyCopy('Lusi', 20, '女');
console.log(applyCopy.name, applyCopy.age, applyCopy.gender); // Lusi 20 女
- 多态:基于继承,父类可以指向不同的子类,父类调用同一个方法时,不同的子类执行的效果不一样。
function beGoodAt(animal) {
animal.show();
};
var Monkey = function() {};
Monkey.prototype.show = function() {
console.log('猴子擅长于爬树');
}
var Cheetah = function() {}
Cheetah.prototype.show = function() {
console.log('猎豹擅长于奔跑');
}
beGoodAt(new Monkey()); // 猴子擅长于爬树
beGoodAt(new Cheetah()); // 猎豹擅长于奔跑