对象
JavaScript的内置对象
JavaScript常见内置对象有Object、Math、String、Array、Number、Function、Boolean、JSON等,其中Object是所有对象的基类,采用了原型继承方式
Boolean:逻辑对象
-
Boolean的声明:声明方式有两种。一是使用字面量方式声明的变量,使用typeof检测是Boolean类型;二是使用new关键字声明的变量,使用typeof检测是Object类型
var boolean = true; // 使用字面量方式声明 var newBoolean = new Boolean(false); // 使用 new 关键字声明 console.log(typeof boolean); // 使用 typeof 检测的数据类型为 Boolean console.log(typeof newBoolean); // 使用 typeof 检测的数据类型为 Object
-
Boolean转换函数:将非布尔值转换为布尔值。如果逻辑对象无初始值或初始值为0、-0、null、" "、false、undefined、NaN,那么返回的值为 false;否则,其值为 true
Number:数字对象
构造函数Number()可以不与运算符new一起使用,而直接作为转化函数来使用
-
Number的声明
var num1 = 10; // 字面量声明 var num2 = new Number(10); // new 关键字声明 console.log(typeof num1); // 使用 typeof 检测的数据类型为 Number console.log(typeof num2); // 使用 typeof 检测的数据类型为 Object
-
Number的属性
Number.MAX_VALUE; //MIN_VALUE:Number 对象的属性,可表示的最小数 Number.MIN_VALUE; //MAX_VALUE:Number 对象的属性,可表示的最大数
-
Number的方法
(1)toString():Number对象的方法,将数字转为字符串,相当于num+" "
var str = num1.toString();
(2)toFixed(n):Number对象的方法,将数字转为字符串,保留n位小数,四舍五入
var num = new Number(10.128); console.log(num.toFixed(2)); //保留两位小数 ,结果为 10.13
(3)valueOf():Number 对象的方法,返回 Number 对象的基本数字值
(4)toLocaleString():Number 对象的方法,将数字按照本地格式的顺序转为字符串。一 般三个为一组加逗号
var num1 = 101123128; var str = num1.toString(); var str = str.toLocaleString() console.log(str); // 打印结果为 101,123,128
(5)toPrecision(n):Number 对象的方法,将数字格式化为指定长度,n 为不含小数点的所有位数和
var num1 = 101123128.456123; var str = num1.toPrecision(10); console.log(str); // 打印结果为 101123128.5 一共 10 位数
String:字符串对象
-
String对象的属性:length,表示字符串中的字符个数
str.length; //返回字符串的长度
-
String对象的方法
(1)toLowerCase():所有字符转为小写
(2)toUpperCase():所有字符转为大写
(3)charAt(n):截取字符串中第n个字符
(4)indexOf(“查询子串”,index):查询从 index 开始的,第一个子串的索引。没找到返回 -1,与数组的 indexOf()方法相同
(5)substring(begin,end):截取子串,两个参数中begin必选,end可选。只写一个参数时表示从begin开始直到最后,写两个参数时,从begin开始end结束,左闭右开
(6)replace(“old”,“new”):将字符串中第一个old换为new
第一个参数可以为普通字符串,也可以为正则表达式
var str1 = str.replace("a","*"); // 只替换字符串的第一个 a 为* var str1 = str.replace(/a/g,"*"); // 使用正则,替换字符串中的所有 a 为*
(7)split(" "):将字符串通过指定分隔符分为数组,只传入空字符串时会把单个字符存入数组
var str1=str.split().join(); //使用空格将字符串拆为数组后又通过空格将字符串连接
注意:JavaScript的字符串不可变,String类的方法都不能改变字符串的内容,而是返回全新字符串
Date:日期对象
-
实例化方式
//在没有参数的情况下对其进行实例化 var myDate = new Date(); // 获取当前最新时间 var myDate = new Date(milliseconds); //传递 milliseconds 作为一个参数 var myDate = new Date(dateString); //将一个日期字符串作为一个参数传递 var myDate = new Date(year, month, day, hours, minutes,seconds, milliseconds); //传递多个参数来创建一个完整的日期
-
常用方法
Math:算术对象
算术对象的方法:
算术对象的属性:
JavaScript自定义对象
对象的声明
-
字面量声明
var obj = { key1: value1, // obj 属性 key2: value2, func : function(){} // obj 方法 }
-
new关键字声明
var obj = new Object(); obj.name = "小王"; obj.say = function(){ console.log("我是:"+this.name); }
对象的属性和方法
-
调用
(1)通过运算符(.)调用
//对象内部: this.属性名 this.方法名() //对象外部: 对象名.属性名 对象名.方法名()
注意:在对象中直接写变量名,默认为调用全局变量,如果需调用对象自身属性,则必须通过 this 关键字
(2)通过[“key”]调用
对象名["属性名"] 对象名["方法名"]() //如果key中包含特殊字符,无法使用第一种方式,则必须使用第二种方式
-
删除对象的属性方法
delete person.age; // 删除 Person 对象的 age 属性
面向对象
类与对象
JavaScript中类的定义方法和函数定义方法一样,所以定义类的同时就定义了构造方法
function 类名(属性名 1){
this.属性名 1 = 属性名 1;
this.方法名 = function(){
// 方法中要调用自身属性,必须使用 this.属性名 调用
}
}
//示例:
function Person(name,sex){ // 类,同时定义构造方法
this.eat=function(){ // 类中的方法
alert("eating");
}
this.name = name; // 类中的属性
this.sex = sex;
}
通过类实例化出一个新的对象,实例化对象的时候会执行构造函数
var obj = new 类名(属性 1 的具体值);
obj.属性名; // 调用属性
obj.方法(); // 调用方法
//对象属性的删除
delete 对象名.属性名
delete zhangSan.name; // 删除 zhangSan 对象的属性 name
对象与数组一样是引用数据类型,也就是说当new一个对象时,这个对象变量存储的实际上是对象的地址,在对象赋值时,赋的其实也是地址
function Person(){}
var zhangsan = new Person(); // zhangsan 对象实际存的是地址
var lisi = zhangsan; // 赋值时,实际是将 zhangsan 存的地址给了 lisi
lisi.name = "李四"; // 李四通过地址,修改了 name 属性
console.log(zhangsan.name); // 张三再通过地址打开对象,实际 name 属性值已经改变
constructor和instanceof
先定义一个类并实例化出一个对象,后面举例将以此为基础
function Person(name){
this.name = name; // 类的属性
this.say = function(){ } // 类的方法
}
// 从类中实例化出一个对象,并给对象的属性赋值。
var xiaowang = new Person("小王");
-
constructor属性:返回当前对象的构造函数
xiaowang.constructor==Person //true
-
instanceof属性:判断对象是否为某个类的实例
console.log(xiaowang instanceof Person); //true console.log(xiaowang instanceof Object); //true console.log(Person instanceof Object); //true,函数也属于对象
for-in:对象的遍历
for(var prop in xiaowang){
console.log("xiaowang的属性有"+xiaowang[prop]);
}
//prop表示xiaowang这个对象的每一个键值对的键,所以用xiaowang[prop]读取每个属性的值
成员属性、静态属性和私有属性
一个类可以拥有多种不同类型的属性和方法。在类中使用 this 声明的称为成员属性,在类外部使用类名声明的称为静态属性,而在类中使用 var 声明的属性称为私有属性
-
成员属性,也叫实例属性,属于实例化出的对象,通过“对象.属性”调用
alert(xiaowang.name); //调用成员属性
-
成员方法,也叫实例方法,属于实例化出的对象,通过“对象.方法”调用
xiaowang.say(); //调用成员方法 //示例: function Person(name){ this.name = name;// 声明成员属性 this.say = function(){}// 声明成员方法 } var xiaowang = new Person("小王"); xiaowang.age = 14; // 追加成员属性 alert(xiaowang.name); // 调用成员属性 xiaowang.say(); // 调用成员方法
-
静态属性,也叫类属性,是属于类(构造函数)的属性,通过“类名.属性”调用
function Person(name){} //声明一个类 Person.sex="男"; //声明类属性 alert(Person.age); //调用类属性
-
静态方法,也叫类方法,是属于类(构造函数)的方法,通过“类名.方法”调用
function Person(name){} // 声明一个类 Person.sex = "男"; // 声明类属性 Person.say = function(){ alert(“我说话了!”); }; // 声明类方法 Person.say(); // 调用类方法
注意:
成员属性是属于实例化出的对象的,会出现在新对象的属性上;而类属性是属于构造函数自己的,不会出现在新对象的属性上
function Person(name){} // 声明一个类 Person.sex = "女"; // 声明类属性 var xiaowang = new Person("小王"); // new 一个对象 alert(xiaowang.sex); // 无法调用。类属性只能用类名调用,即使用 Person.sex 调用
-
私有属性和私有方法
function(){ var num=1; //私有属性 function func(){ } //私有方法 }
注意:
私有属性、私有方法的作用域都只在构造函数内部有效,只能在其内部使用,在构造函数外部,无论是对象名还是类名都无法调用
function Person(names){ this.name = names; var sex = "男"; alert(sex); // 私有属性只能在类内部使用 } alert(Person.sex); // 无法调用 var xiaowang = new Person("小王"); alert(xiaowang.sex); // 无法调用
this关键字
this的指向
-
this的指向的三个基本要素:
(1)this 指向的永远只可能是对象
(2)this 指向谁,永远不取决于 this 写在哪,而是取决于函数在哪调用
(3)this 指向的对象,称为函数的上下文(context),也叫函数的调用者
-
this指向的是函数的调用者,而不是函数的声明者。也就是说this指向谁与函数调用方式息息相关
(1)函数名()直接调用,this指向window对象
function func(){ // 下面示例中用到的 func 函数都是指的此函数 console.log(this); } func(); // this--->window 通过函数名() 调用的,this 永远指向 window 对象
(2)对象.函数名()调用,this指向这个对象
//将 func 函数名当作 obj 对象的一个方法,然后使用对象名.方法名调用,这个时候函数里面的 this 指向 obj 对象 var obj = { // 狭义对象 name:"obj", func1 :func }; obj.func1(); // this--->obj //对象的调用还有一种情况,就是使用 getElementById 取到一个 div 控件,是一种广义的对象,使用它调用函数,则函数中的 this 指向这个 div 对象 document.getElementById("div").onclick = function(){ // 广义对象 this.style.backgroundColor = "red"; } // this--->div
(3)数组下标调用,this指向这个数组,函数作为数组的一个元素
var arr = [func,1,2,3]; arr[0](); // this--->arr
(4)回调函数调用,函数作为window内置函数的回调函数,this指向window,如setInterval、setTimeout等
setTimeout(func,1000); // this--->window
(5)new关键字调用,函数作为构造函数,this指向新new出的对象
var obj = new func(); // this---> 新 new 出的 obj
原型和原型链
一个对象的_ _ proto _ _的最终指向就是这个对象的原型链
_ _proto _ _和prototype
-
prototype(函数的原型) 函数才有 prototype。prototype 是一个对象,指向了当前构造函数的引用地址。通过 prototype 可以为对象在运行期间添加新的属性和方法。
-
_ _ proto _ (对象的原型对象) 所有对象都要 _proto _ 属性(这里的对象除了人们理解的狭义对象,也包括函数、数组 等对象)。当用构造函数实例化(new)一个对象时,会将新对象的 _ proto _ _属性指在构造函数的 prototype。
function Person(){}
var xiaowang=new Person();
console.log(xiaowang.__proto__==Person.prototype); //true
原型链
由原型层层连接起来的结构就构成的原型链
function Person(){}
var xiaowang = new Person();
原型链的指向规则:
(1)通过构造函数 new 出的对象,新对象的__proto__指向构造函数的 prototype
(2)所有函数的__proto__ 指向 function()的 prototype
(3)非构造函数 new 出的对象的__proto__指向 Object 的 prototype
(4)Object()的 prototype 的__proto__指向 null
(5)所有对象最终都会指向 Object()的 prototype
原型属性和原型方法
原型属性和原型方法是写在构造函数的 prototype 上。当使用构造函数实例化对象时, 该属性方法会进入新对象的__proto__上
Person.prototype.name = "";
Person.prototype.func = function(){};
//习惯上将属性写为成员属性,方法写为原型方法
function Person(){
this.name = "xiaowang";
}
Person.prototype.say = function(){}
封装
把属性和方法封装成一个类,并通过类名拿到对象,就是类的封装;将一段段重复使用的代码封装成一个个方法是方法的封装;属性的封装就是将类中的属性进行私有化处理,对外不能直接使用对象名访问私有属性,同时需要提供专门用于设置和读取私有属性的get/set方法,让外部使用人们提供的方法对属性进行操作
继承
子类继承父类,子类可以自动拥有父类的所有属性和方法
实现继承的方法
-
扩展 Object 的 prototype 实现继承 :通过循环,将父类对象的所有属性和方法,全部赋给子类对象。关键点在于 for-in 循环,即使不扩展 Object,也能通过简单的循环实现操作。
本质:自己写个方法,将父类的所有属性和方法通过遍历循环,逐个复制给子类
1.声明父类 function Parent(){} 2.声明子类 function Child(){} 3.通过原型给Object对象添加一个扩展方法 Object.prototype.customExtend=function(parObj){ for(var i in parObj){ //通过for-in循环,把父类所有属性方法赋值给子类 this[i]=parObj[i]; } } 4.子类对象调用扩展方法 Child.customExtend(Parent);
缺点:(1)无法通过一次实例化直接得到完整子类对象,而需要先取到子类和父类对象,再手动合并
(2)扩展Object的继承方法会保留在子类对象上
-
使用原型实现继承:就是将子类的prototype指向父类对象。将父类对象赋值给子类的 prototype,那么父类对象的属性和方法就会出现在子类的 prototype 中。那么实例化时,子类的 prototype 又会到子类对象的__proto__ 中,最终父类对象的属性和方法会出现在子类对象的__proto__中
1.声明父类 function Parent(){} 2.声明子类 function Child(){} 3.把在子类对象的原型对象声明为父类的实例 Child.prototype=new Parent();
特点:(1)子类自身的所有属性都是成员属性,父类继承过来的属性都是原型属性
(2)无法通过一步实例化拿到完整的子类对象
-
使用 call 和 apply 实现继承:通过函数名调用方法,强行将函数中的this指向某个对象。定义子类时,在子类中使用三个函数调用父类,将父类函数的 this 指向为子类函数的 this
func.call(func的this指向的obj,参数1,参数2....); //call写法 func.apply(func的this指向的obj,[参数1,参数2....]); //apply写法
具体步骤:
1.声明父类 function Parent(){} 2.声明子类 function Child(){} 3.在子类中通过call方法或者apply方法去调用父类 function Child(){ Parent.call(this,....); //将父类函数中的this强行绑定为子类的this }
闭包
https://www.runoob.com/js/js-function-closures.html