1.继承的方式
- 原型链
继承了太多没用的属性 - 借用构造函数(call方法)
function Person(name, age, sex) {
this.name = name;
}
(1)不能继承构造函数的原型
(2)在视觉上省了空间,但是每次构造函数都要多走一个构造函数
- 共享原型
Father.prototype.lastName = "Deng";
function Father() {}
function Son() {}
Son.prototype = Father.prototype;
var son = new Son();
var father = new Father();
抽象为一个继承功能
Father.prototype.lastName = "Deng";
function Father() {}
function Son() {}
//抽象为继承函数
function inherit(Target, Origin) {
Target.prototype = Origin.prototype;
}
inherit(Son, Father);
var son = new Son();
//注意:后两个语句不能换位置
//一定要先继承再用
- 圣杯模式(在共享原型上加上原型链的使用)
function inherit(Target, Origin) {
//添加一个中间层构造函数
function F {};
//令中间层F的原型和Origin的原型相等,
F.prototype = Origin.prototype;
Target.prototype = new F();
//new一个F(),是又创建了一个新的原型空间
//这样即继承了Origin的属性,又可以添加自己的属性
//此时对象构造器的指向为
// son.__proto__ --> new F() --> Father.prototype --> 构造器constructor是Father
//因此Target的构造器更改为自身
Target.prototype.constructor = Target;
//给Target增加一个属性超集uber,方便以后查看其继承自谁
Target.prototype.uber = Origin.prototype;
}
使用闭包升级方法
function inherit(function() {
var F = function() {};
return function (Target, Origin) {
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
2.命名空间
管理变量,防止污染全局,适用于模块化开发
- 命名空间
利用对象{}中的内容可以是对象{},层层嵌套对象,形成分隔的命名空间
var org = {
department1 : {
person1 : {
name : 'abc',
age : 123
},
person2 : {
name : 'b'
}
},
department2 : {
person1 : {},
person2 : {}
}
}
//使用某个变量
//方法一
org.department1.person1.name;
//方法二
var person1 = org.department1.person1;
person1.name;
- webpack
- 用闭包私有化变量
var init = (function() {
var name = 'abc';
function callName() {
console.log(name);
}
return function() {
callName();
}
}())
//init返回的是函数,才能以函数的形式执行
//如果没有将callName放入函数中,就算callName本身是函数也不能这样执行
//这样会报错,说init不是一个函数
init();
在开发中,将所有的入口函数都命名为为init
3.链式调用(模仿jQuery)
//jQuery中的链式调用形式
$('div').css('background-color','red').width(100).height(100).css('position','absolute');
//可以在调用完一个对象属性方法后继续调用其他的
var person = {
drink : function() {
console.log('drink!');
return this;
//返回this重新指向对象
},
eat : function() {
console.log('eat');
return this;
},
sleep : function() {
console.log('sleep');
return this;
}
}
//这样就可以链式调用函数方法
person.drink().sleep().eat();
4.访问属性的方法
- 方法一:
obj.name
不够灵活,不能实现属性名的拼接
obj.name在系统内部中发生了自动转换,被转换为`obj[‘name’]
- 方法二:
obj['name']
(建议使用这种,便于属性名字符拼接)
注意:属性名必须加引号,不然不能识别
5.对象枚举
- for in
var obj = {
name : 'kathy',
age : 13,
sex : 'male'
}
//遍历
for(var prop in obj) {
console.log(obj[prop]);
}
prop
代表对象属性,可以被定义为任何变量,只是一个名字。
注意最后一行打印代码,不能写成obj.prop,因为系统内部的转换,见4,系统会将这行语句识别成obj的prop属性
且不能加引号成为obj[‘prop’],因为本身遍历时就已将属性保存到prop中,就是字符串,所以不用多此一举加引号
- hasOwnProperty
obj.hasOwnProperty(prop);
//若属性时原型的将返回true
for in
方法在遍历对象的属性时,会返回包括原型上的东西,因此有时造成冗余
for in
返回的原型属性均是自己定义的属性,系统定义的属性并不返回
//在前面的代码中加入hasOwnProperty过滤原型的属性
for(var prop in obj) {
if(obj.hasOwnProperty(prop)) {
console.log(obj[prop]);
}
}
- in
判断属性是否属于对象
'height' in obj;
//注意属性要加引号,不加引号就是变量的意思,而变量不会在对象中
in与hasOwnProperty的区别是:
in只能判断对象是否能访问到这个属性,不能排除原型上的属性。
- instanceof
看A对象的原型链上有没有B的原型,是返回true
A instanceof B
判断是数组[]还是对象{}的三个方法:
(1)构造器constructor
[].cosntructor
//输出 function Array() {}
//注意对象要先定义,不能直接使用{}代表对象
var obj = {};
obj.constructor
//输出 function Object() {}
(2)instanceof Array
[] instanceof Array;
// true
var obj = {};
obj instanceof Array;
// false
(3)toString
Object.prototype.toString.call(要判断类型的)
//使用call改变this的指向,从而判断参数的类型
Object.prototype.toString.call([]);
// [object Array]
Object.prototype.toString.call(123);
// [object Number]
Object.prototype.toString.call({});
// [object Object]