JavaScript简述
基础语法
- 输出内容:
<script>
// 控制浏览器弹出一个警告框
alert("警告!");
// 让计算机在页面输出一个内容
document.write("嘿嘿"); //可以向body中输出内容
// 向控制台输出内容
console.log("我在控制台呢");
</script>
- 将js代码写在标签属性中
<body>
<!-- 可以将js代码写在标签的onclick属性中,当点击按钮时,js代码才会执行 -->
<button onclick="alert('别点我啊你');">干嘛?别点我</button>
<!--可以向js代码写在超链接的href属性中,这样当点击超链接时会执行js代码 -->
<a href="javascript:alert('你完了')">你点我一下呗</a>
</body>
- 将js代码编写到外部js文件中,通过script标签引入
<script type="text/javascript" src="js/test1.js"></script>
- 数据类型
<!-- 数据类型指的就是字面量类型
在js中一共有六种数据类型
String 字符型
Number 数值
Boolean 布尔值
Null 空值
Undefined 未定义
Object 对象
其中Object属于引用数据类型,其他属于基本数据类型 -->
<script>
var a = '123'
var b = 123;
// 使用typeof运算符检查一个变量的类型: typeof 变量名
console.log(typeof a);
console.log(typeof b);
//js中可以表示数字的最大值 Number.MAX_VALUE
// 1.7976931348623157e+308
a = Number.MAX_VALUE * Number.MAX_VALUE;
console.log(a);
// 如果使用Number表示的数字超过了最大值,则会返回一个Infinity表示正无穷,-Infinity表示负无穷。
a = Infinity;
a = 'abc' * 'abc';
console.log(a); //NaN 是一个特殊的数字,表示Not A Number
a = NaN;
console.log(typeof a);
// Number.MIN_VALUE 大于0的最小值
a = Number.MIN_VALUE;
console.log(a); //5e-324
// 在js中整数的运算基本准确
var c = 123 + 456;
console.log(c);
// 进行浮点数运算,可能得到不精确的值,所以不使用js进行比较精确的运算
var c = 0.1 + 0.2;
console.log(c);
// 布尔值
var bool = true;
console.log(bool);
// Null类型的值只有一个:Null 表示一个空对象
var n = null;
console.log(typeof n); //返回object
// undefined类型只有一个:undefind 当声明表量,但是不赋值时,它的值就是undefind
var u;
console.log(u);
// 类型转换
// 将其他数据类型转换为String类型
// 1.调用被转换类型的toString()方法
var a = 123;
a = a.toString();
console.log(typeof a);
// null 和 undefined 两个值没有toString()方法,调用报错
// 调用String()函数,并将转换的数据作为参数传递
// 对于Number和Boolean实际上就是调用的toString()方法
// 但是对于null 和 undefined, 就不会调用toString方法,它将null直接转换为'null',undefined转换为"undefined"
var m = 123;
String(m);
m = null;
console.log(m);
console.log(typeof m);
// 将其他数据类型转换为Number
// 方式一.调用Number()函数
// 字符串 ---> 数字
// 1.如果是纯数字的字符串,则直接转换为数字
// 2.如果是字符串中有非数字的内容,则转换为NaN
// 3.如果是空字符串,则转换为0
// 布尔 ----> 数字
// true 转换为1
// false 转换为0
// null ----> 数字 0
// undefined ----> 数字 NaN
var a = "123";
a = Number(a);
var b = "123abc";
b = Number(b);
console.log(typeof a);
console.log(a);
console.log(typeof b);
console.log(b);
var c = '';
c = Number(c);
console.log(c);
a = "123px";
a = Number(a);
console.log(a);
// 方式二:这种方式专门用于字符串
// parseInt() 把一个字符串转换为整数 (可以将前面有效的整数内容取出来,转换为Number)
// parseFloat() 把一个字符串转换为一个浮点数 (类似)
a = "123px";
a = parseInt(a);
b = "123.456px";
b = parseFloat(b);
console.log(typeof a);
console.log(a);
console.log(typeof b);
console.log(b);
// 如果对非String使用paeseInt()或parseFloat(),它会先将其转换为String类型再操作
a = true;
a = parseInt(a);
a = 198.123;
a = parseInt(a); //先转换为字符串,间接取整
console.log(typeof a);
console.log(a);
// 将其他类型转换为boolean,使用Boolean()函数
// 数字 ---> 布尔 除了0,NaN,其余都是true;
// 字符串 ---> 布尔 null和undefined 都会转换为false
// 对象也会转换为true
var a = 123;
a = 0;
a = NaN;
a = undefined;
a = null;
a = Boolean(a);
console.log(typeof a);
console.log(a);
</script>
- 进制表示
// 在js中,如果需要表示十六进制的数字,以0x开头;
// 如果需要表示八进制的数字,以0开头
// 如果需要表示二进制的数字,以0b开头,但是不是所以浏览器都支持
// 十六进制
a = 0x10;
// 八进制
a = 070;
// 二进制
// a = 0b10;
console.log(a);
// 像"070"这种字符串,有些浏览器会当成八进制解析,有些会当成十进制解析
a = "070";
// a = parseInt(a);
a = parseInt(a, 10);
console.log(typeof a);
console.log(a);
- 运算符
算术运算符
<script>
/*
* 算数运算符:+ - * / %
* 当对非Number类型的值进行运算时,会将这些值转换为Number,然后操作
* 任何值和NaN做运算都得NaN
* 如果对字符串进行+运算,会拼在一起返回字符串
* 任何值和字符串做加运算,都会先转换为字符串,然后做字符串拼串操
*/
var a = 123;
var result = a + 1;
console.log(a); //123
console.log(result); //124
result = true + 1;
console.log(result); //2 把true当成1
result = true + false;
console.log(result); //1 把false当成0
result = 2 + null; //2
result = 2 + NaN; //NaN
result = "123" + "456"; //"123456"
result = 123 + "1"; //"1231"
// 利用这一特点将任意数据类型转换为String,只需要为任意的数据类型+一个""即可
// 这是一种隐式的类型转换,由浏览器自动完成,实际上它也是调用String()
var c = 123;
c = c + "";
console.log(typeof c); //String
console.log("c =" + c); // "123"
</script>
一元运算符(自增自减)
/*
*一元运算符,只需要一个操作数
* +正号
* -负号
* 对于非Number类型的值,先转换为Number,原理和Number()函数一样
*/
var a = true;
a = -a;
console.log(a); //-1
var result = 1 + +'2' + 3; //6
// 自增
var a = 1;
//使a自增 a++的值等于原变量的值,++a的值等于新值
a++;
++a;
console.log('a =' + a);
console.log('++a =' + ++a); //++a = 2
console.log('a++ =' + a++); //a++ =1
var x = 20;
//20+22+22=64
var result = x++ + ++x + x;
// 自减 (同理)
var b = 2;
b--;
--b;
console.log('b =' + b);
逻辑运算符
/*
*js为我们提供了三种逻辑运算符 || 或 && 与 ! 非
*非运算! :如果对非Boolean值进行取反,会先转换为Boolean类型
*隐式数据类型转换:可以利用这一特点,将任意数据类型取反两次,将其转换为布尔值,原理和Boolean()函数一样
*与运算&& :只要有一个false就返回false,只有两个都为true时返回true
*js中的与属于短路与,如果第一个为false,则不会检查第二个值
*或运算|| :只要有一个true就返回true
*js中的或属于短路或,如果第一个为true,则不会检查第二个值
* && || 非布尔值的情况
*对于非布尔值进行与或运算时会先将其转换为布尔值,并返回原值
*与运算:
*如果第一个值为true,则必然返回第二个值;
*如果第一个值为false,则直接返回第一个值。
*或运算:
*如果第一个值为true,则直接返回第一个值
*如果第一个值为false,则返回第二个值
* */
var a = 10;
a = !!a;
console.log(a); //true
var result = true && true;
result = false && false;
console.log(result);
true && alert('还要检查我呢!')
false && alert('前面都false了还检查啥呢!')
result = false || false;
result = true || false;
result = false || true
console.log(result);
true || alert('不用看我了哥');
false || alert('还得检查我嘞!');
// 非布尔值的与或,会先转换为布尔值,然后再运算,并且返回原值
// true && true
// 如果两个值都为true,返回后边的
var result = 1 && 2;
console.log('result =' + result); //2
var result = 2 && 1;
console.log('result =' + result); //1
// 如果两个值中有false则返回靠前的false
// false && false
result = 0 && 2; //0
result = 2 && 0; //0
//false && false
result = NaN && 0; //NaN
result = 0 && NaN; //0
// ||与 && 一样短路原理
赋值运算符+关系运算符
/**
* 赋值运算符:可以将符号右则的值赋值给符号左边的变量
* a += 5 等价与 a = a + 5
* 关系运算符:通过关系运算符比较两个值之间的大小关系,成立返回true,不成立返回false
* > < == >= <=
* 对于非数值进行比较时,先转换为数值,true为1,false为0
*
*
*
**/
var result = 5 > 10;
console.log(result);
// 任何值和NaN作比较都是false
console.log(10 <= 'hello'); //false
// 如果符号两则都是字符串时,不会将其转换为数字比较,,而会比较字符串中字符的Unicode编码
console.log('1' < '5'); //true
console.log('11' < '5'); //true
// 比较字符编码时时一位一位进行比较
console.log('abc' < 'b'); //true
// 比较汉字没有意义
// 如果比较两个字符串型的数字,可能得到不可预期结果
// 注意:在比较两个字符串型的数字时,一定一定一定要转型
console.log('11111' < +'5'); //false
// 相等运算符 ==
// 当类型不同时,会自动进行类型转换,将其转换为相同类型,然后比较
var a = 10;
console.log(a == 5); //false
console.log('1' == 1); //true
console.log(true == '1'); //true
console.log(null == 0); //false
//undefined 衍生自null ,所以这两个值做相等判断时会返回true
console.log(undefined == null); //true
// NaN 不和任何值相等,包括他本身
console.log(NaN == NaN); //false
var b = NaN;
// 判断b 的值是否是NaN
console.log(b == NaN); //false
// 可以通过isNaN()函数来判断一个值是否是NaN
console.log(isNaN(b)); //true
// 不相等运算符
// === 全等 用来判断两个值是否相等,和相等类似,不同的是不会进行自动类型转换
console.log('123' == 123); //true
console.log('123' === 123); //false
console.log(null === undefined); //false
// !== 不全等 用来判断两个值是否不全等,和不等类似,不同的是不会进行自动类型转换
// 如果类型不同,直接返回false
条件运算符
/**
*条件运算符,也叫三元运算符
*语法:
* 条件表达式 ? 语句1 :语句2
*--执行流程:条件运算符在执行时,首先对条件表达式进行求值,
* 如果该值为true,则执行语句1,并且返回执行结果,
* 如果该值为false,则执行语句2,并且返回执行结果。
**/
true ? alert("语句1") : alert("语句2");
var a = 10;
var b = 20;
a > b ? alert('a') : alert('b大');
var max = a > b ? a : b;
console.log('max = ' + max);
var c = 90;
var max = a > b ? (a > c ? a : c) : (b > c ? b : c);
console.log(max);
代码块 {} :一个{}属于一个代码块,js中的代码块只有分组的作用。
流程控制语句
<script>
/**
* 流程控制语句:
* 1.条件判断语句: if语句 可以放到代码块中
* 2.条件分支语句
* 3.循环语句
*
*
* */
if (true) {
alert('if语句');
alert('哈哈!');
}
var ago = 90;
if (ago >= 60) {
alert("你超过60了");
} else {
alert("你不到60哎!");
}
if (ago >= 50) {
alert('11');
} else if (ago >= 80) {
alert('22');
} else {
alert('33');
}
// switch 语句
var num1 = 1;
switch (num1) {
case 1:
console.log('一');
break;
case 2:
console.log('二');
break;
default:
console.log('非法');
break;
}
// while 语句
// 向页面输出连续的语句
var n = 1;
while (n < 5) {
document.write(n + '<br/>');
n++;
}
// do while 语句
var n = 2;
do {
document.write('哈哈')
}
while (n < 5) {
alert(1);
n++;
}
// for 语句
for (var i = 0; i <= 2; i++) {
alert(i);
}
//for循环三部分都可以省略,也可以写在外部;
var i = 0;
for (; i < 2;) {
alert(i);
i++;
}
// for(;;){
// alert('hello');//死循环
// }
// 嵌套的for循环
/*
通过程序在页面输出:
****
***
**
*
*/
for (var i = 4; i >= 0; i--) {
for (var j = 0; j < i; j++) {
document.write('*');
}
document.write('<br/>');
}
</script>
对象
<script>
/**
*对象的分类:
* 1.内建对象:又ES标准定义的对象,如 Math String
* 2.宿主对象:由js的运行环境提供的对象,目前来说主要值由浏览器提供的对象,如BOM DOM
* 3.自定义对象:由开发人员创建的对象
*/
// 创建对象
// 使用new 关键字调用的函数,是构造函数constructor,构造函数是专门用来创建对象的
var obj = new Object();
console.log(typeof obj); //object
//向对象中添加属性:语法:对象.属性名 = 属性值
obj.name = "对象";
console.log(obj);
//读取对象的属性:语法:对象.属性名
console.log(obj.name);
// 修改对象属性:语法:对象.属性名 = 新属性值
obj.name = "女朋友";
//删除对象的属性:语法:delete 对象.属性名
delete obj.name;
console.log(obj.name);
// 对象的属性名不强制要求遵守标识符的规范,但是尽量遵守规范
// 如果要使用特殊的属性名,不能采用.的方式来操作,如:obj.123 = 456;
// 需要使用另一种方式:语法: 对象["属性名"] = 属性值 读取时也要采用这种方式
obj["123"] = 456;
console.log(obj["123"]);
// 使用[]这种形式去操作属性,更加灵活
// 在[]中可以直接转递一个变量,这样变量值时多少就会去读取那个属性
obj["123"] = 789;
obj["nh"] = "你好";
var n = "nh";
console.log(obj[n]); //你好
// js中的属性值可以时任意类型
var obj1 = new Object();
obj1.name = "面码";
obj.test = obj1;
console.log(obj.test.name);
//
// in 运算符:通过该运算符检查一个对象中是否含有指定的属性,如果有返回true,没有返回false
// 语法: "属性名" in 对象
console.log("test" in obj); //true
console.log("test" in obj1); //false
// 基本数据类型:String Number Boolean Null Undefined
// 引用数据类型:Object
// 区别:基本数据变量内存地址不同,而obja 和objb指向同一个对象(内存地址),基本数据类型保存的是值,对象保存的是地址。
/*
js中的变量都是保存在栈内存中的,基本数据类型的值直接在栈内存中存储,值与值之间独立存在,修改不会对其他值造成影响
对象是保存到堆内存中的,每创建一个对象就会在堆内存中开辟一个新的空间,而变量保存的是对象的地址(对象的引用)
如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响。
*/
var obja = new Object();
obj.name = "小呆呆";
var objb = obja;
// 修改obj 的name属性
obja.name = "大笨蛋";
console.log(obja.name); //大笨蛋
console.log(objb.name); //大笨蛋
// 设置objb 为null;
objb = null;
console.log(obja);//object
console.log(objb);//null
/**
*对象字面量
* 使用对象字面量,可以在创建对象时直接指定对象中的属性
* 语法:{属性名:属性值,属性名:属性值...}
* 对象变量的属性名可以加引号也可以不加,特殊的必须加
*
*
* */
// 创建一个对象:
var obj = new Object();
// 使用对象字面量来创建一个对象
var obj = {};
var obj2 = {
name :"哈哈",
ago : 10,
test:{
name:"呵呵"
}
};
console.log(obj2);
</script>
函数
/**
* 函数
* --函数也是一个对象
* --函数中可以封装些功能(代码),在需要时可以执行这些功能(代码)
*
* */
//创建一个函数对象:构造函数(一般不用这个方法)
// 可以将要封装的代码以字符串的形式传递给构造函数
var fun = new Function("console.log('hello,第一个函数');");
console.log(fun);
console.log(typeof fun);
// 调用函数:函数对象()
fun();
fun.hello = "你好";
console.log(fun.hello);
// 使用函数声明来创建一个函数
/*语法:function 函数名([形参1,形参2...形参n]){
语句...
}
*/
function fun2() {
console.log('第二个函数');
}
console.log(fun2);
fun2();
// 使用函数表达式来创建一个函数
// 语法:var 函数名 = function([形参1,形参2...形参n]){
// 语句...
// }
var fun3 = function() {
console.log('匿名函数');
};
fun3();
/**
* 函数的参数
*
* */
// 定义一个用来求两个数和的函数
function sum(a, b) {
console.log('a =' + a);
console.log('b =' + b);
console.log(a + b);
}
sum(1, 2);
// 调用函数时解析器不会检查实参的类型,所以要注意可能接收到非法的参数,如果有则需要对参数进行类型检查
// 调用函数时,解析器也不会检查实参的数量,多余实参不会被赋值
// 如果实参的数量少于形参的数量,则没有对应实参的形参将会是undefined
sum("hello", 2);
sum(2);
// 函数的返回值:return
// 如果return语句后不跟任何值相当于返回一个undefined,如果函数中不写return也返回一个undefined
// return 后面可以跟任何值
function sum(a, b, c) {
return a + b + c;
}
var result = sum(1, 2, 3);
alert(result);
var result = alert("hello");
console.log(result); //undefined
// 定义一个函数,可以根据半径计算一个圆的面积,并返回结果
function calcAera(r) {
return 3.14 * r * r;
}
result = calcAera(5);
console.log(result);
// 返回值可以是任意数据类型,也可以是一个对象,也可以是一个函数
function fun2() {
var obj = {
name: '嘿嘿'
};
return obj;
}
var a = fun2();
console.log('a = ' + a.name);
function funx() {
function funy() {
alert('我是f4');
}
// fun4();
// 返回funy函数的返回值
// return funy();
// 将funy函数对象作为返回值返回
return funy;
}
var a = funx();
console.log(a);
// 相当于调用funy
a();
funx()();
/*
立即执行函数:函数定义完,立即被调用
往往只会执行一次!
*/
// 函数对象()
// (function(){
// alert('我是一个匿名函数---');
// })();
(function(a, b) {
console.log('a = ' + a);
console.log('b = ' + b);
})(123, 456);
/**
*方法:
* 如果一个函数作为一个对象的属性保存,称这个函数是这个对象的方法
* 但是它只是名称上的区别没有其他区别
**/
// 对象的属性值可以是任何数据类型,也可以是函数
var obj = new Object();
obj.name = '你好';
obj.sayhello = function() {
console.log(obj.name);
};
// 调方法
obj.sayhello();
// 调函数
fun();
var obj = {
name: 'hh',
book: '钢铁是怎样炼成的',
sayhello: function() {
console.log('hello');
}
};
obj.sayhello();
/**
* 枚举对象中的属性
* 使用 for...in 语句
* 语法:
* for(var 变量 in 对象){
* }
*
* */
// n 是属性名
for (var n in obj) {
console.log('属性名:' + n);
// console.log(obj.n);
console.log('属性值:' + obj[n]);
}
作用域:
/**
* 在js中有两种作用域
* 1.全局作用域
* 直接编写在script标签中的,都在全局作用域
* 在页面打开时创建,在页面关闭时销毁
* 在全局作用域中有一个全局对象window(代表的是一个浏览器窗口,它由浏览器创建),我们可以直接使用
* 在全局作用域中:
* 创建的变量都会作为window对象的属性保存
* 创建的函数都会作为window对象的方法保存
* 2.函数作用域
* */
var a = 10;
window.b = 20;
console.log(a);
console.log(b);
console.log(window.a);
function funxx() {
console.log('heihei');
};
window.funxx();
window.alert();
// 变量的声明提前:
// 使用var关键字声明的变量,会在所有的代码执行之前被声明
// 但是如果声明变量不使用var ,则变量不会
// 函数的声明提前:
// 使用函数的声明形式创建的函数function(){}它会在所有的代码执行之前就被创建、
// 所以我们可以在函数声明前调用!
// 使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用。
console.log(t); //undefined
var t = 123;
// 相当于:
// var t;
// console.log(t);
// t = 123;
// funn();
funm();
function funm() {
console.log('使用函数声明创建');
}
var funn = function() {
console.log('使用函数表达式创建');
}
// funn();
// funm();
/**
* 函数作用域
* 在函数作用域可以访问到全局作用域的变量;在全局作用域不能访问函数作用域
* 当在函数作用域操作一个变量时,他会先在自身作用域中寻找,如果有就直接使用
* 没有则向上一级作用域中寻找,直到找到全局作用域
* 如果全局作用域中依然没有知道,则报错referenceerror
* 在函数中,访问全局变量,可以使用window对象
*
* 在函数作用域中也有声明提前的特性
* 使用var 关键字声明的变量,会在函数中所有代码执行之前被声明
*
* 函数声明也会在所以代码执行之前执行
* */
function fun() {
funw();
console.log(f);
var f = 2;
// console.log(window.a);
function funw() {
alert('123456');
}
}
this:
/**
* 解析器在调用函数每次都会向函数内部传递一个隐含参数,这个参数就是this,
* this指向的是一个对象,这个对象我们称为函数执行的上下文对象,
* 根据函数调用方式的不同,this会指向不同的对象。
* 1.以函数的形式调用时,this永远都是window
* 2.以方法的形式调用时,this就是调用方法的那个对象
*
* */
var name = '李四';
function fun1(a, b) {
console.log(this);
console.log(name);
console.log(this.name);
};
fun1(12, 34);
// 创建一个对象
var obj1 = {
name: '张三',
sayhello: fun1
};
console.log(obj1.sayhello == fun1); //true
var obj2 = {
name: '王五',
sayhello: fun1
};
obj1.sayhello();
obj2.sayhello();
fun1();
构造函数:
/**
* 使用工厂对象创建对象,使用的构造函数都是object
* 所以创建对象都是object这个类型,就导致我们无法区分多种类型的对象
*
* */
function createPerson(name, age, gender) {
// 创建一个新对象
var obja = new Object();
// 将新对象返回
obja.name = name;
obja.age = age;
obja.gender = gender;
obja.sayName = function() {
alert(this.name);
}
return obja;
}
var objb = createPerson('小明', 13, '男');
var objc = createPerson('小呆', 10, '男');
var objd = createPerson('小瓜', 2, '男');
objb.sayName();
function createDog(name, age) {
var obja = new Object();
obja.name = name;
obja.name = age;
obja.sayName = function() {
alert(thiis.name);
}
return obja;
};
//
var dog1 = createDog('旺财', 2);
console.log(dog1);
console.log(objb);
/**
* 创建一个构造函数
* 构造函数和普通函数的区别就是调用方式的不同
* 普通函数就是直接调用,而构造函数需要使用new关键字来调用。
*
* 构造函数的执行流程:
* 1.立即创建一个新的对象
* 2.将新建对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象
* 3.逐行执行函数中的代码
* 4.将新建的对象作为返回值
*
* 使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。
* 我们将通过一个构造函数创建的对象,成为是该类的实例。
*
* */
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = function() {
alert(this.name);
};
}
// var per = Person();普通函数
var per = new Person('丁小子', 11, '男');
var per2 = new Person('丁子', 10, '女');
var per3 = new Person('叮叮当', 2, '男');
console.log(per);
function Dog() {
};
var dog = new Dog();
console.log(dog);
/*
*使用instanceof 可以检查一个对象是否是一个类的实例
*/
console.log(per instanceof Person); //true
console.log(dog instanceof Person); //false
//所有的对象都是object的后代,所有任何对象和object做instanceof检查时都会返回true
/**
* this的情况:
* 1.当以函数形式调用时,this是window
* 2.当以方法调用时,谁调用方法this就是谁
* 3.当以构造函数的形式调用时,this就是新创建的那个对象
*
* */
/**
* 创建一个Person构造函数
* -在Person构造函数中,为每一个对象都添加了一个sayName方法
* sayName方法是在构造函数内部创建的
* 也就是构造函数每执行一次就会创建一个新的sayName方法,也就是所有的实例的sayName都是唯一的,
* 这样就导致了构造函数每执行一次就会创建一个新的方法,执行1000次就会创建1000个,而且1000个一模一样
* 完全没必要,可以使所有对象1共享同一个方法
*
* */
function Person(name, age) {
this.name = name;
this.age = age;
// function sayName() {
// console.log(this.name);
// };
this.sayName = fun;
};
//将函数定义在全局作用域,污染了全局作用域的命名空间,而且定义在全局作用域中不安全。
function fun() {
console.log(this.name);
};
//创建Person实例
var per = new Person('小子', 2);
var per1 = new Person('小小', 3);
console.log(per.sayName == per1.sayName);
原型对象
// 原型对象:!
/**
* 原型prototype
* 我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
* 这个属性对应着一个对象,这个对象就是我们所谓的原型对象
* 如果函数作为普通函数调用prototype没有任何作用
* 当函数通过构造函数的形式调用时,他所创建的对象中都会有一个隐含的属性指向改构造函数的原型对象
* 我们可以通过__proto__来访问该属性
*
* 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象
* 我们可以将对象中共有的内容,同意设置到新型对象中。
*
* 当我们访问对象的一个属性或方法时,他会先在对象自身中寻找,如果有则直接使用,没有则在原型对象中寻找,
* 直到找到object对象的原型,object对象的原型没有原型,如果在object中依然没有找到,则返回undefined。
*
* 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,
* 这样不用分别为每一个对象添加也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。
*
* */
function Myclass() {
};
Myclass.prototype.a = 123;
Myclass.prototype.sayhello = function() {
alert('hello');
};
var mc = new Myclass();
var mc2 = new Myclass();
console.log(Myclass.prototype);
console.log(mc.__proto__ == Myclass.prototype); //true
console.log(mc.a); //123
mc.a = '我是mc中的a';
console.log(mc.a); //我是mc中的a
mc.sayhello();
Myclass.prototype.name = '我是原型中的名字';
mc.age = 12;
// 使用in检查对象中是否含有某个属性,如果对象中没有但是原型中有,也会返回true
console.log('name' in mc); //true
// 使用对象的hasOwnProperty()来检查对象自身中是否含有该属性
// 使用该方法只有当对象自身中含有属性时,才会返回true
console.log(mc.hasOwnProperty('age'));
console.log(mc.hasOwnProperty('hasOwnProperty'));
console.log(mc.__proto__.__proto__.__proto__); //null
// 当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值
//如果我们希望在输出对象时不输出[object object]可以为对象添加一个toString()方法
per.toString = function() {
return '我是一个person实例';
};
var result = per.toString();
console.log('result =' + result);
console.log(per.__proto__.__proto__.hasOwnProperty('toString'));
console.log(per);
/**
* 在js中拥有自动垃圾回收机制,会自动将这些垃圾对象从内存中销毁,
* 我们不需要也不能进行垃圾回收操作,我们需要做的时将不需要的对象设置为null。
*
* */
数组
/**
* 数组(Array)
* -数组也是一个对象
* -和普通函数对象功能类似,也是用来存储一些值的
* -不同的时普通对象是使用字符串作为属性名
* -而数组是使用数字来作为索引操作元素
*
*
* */
var arr = new Array();
arr[0] = 10;
arr[1] = 20;
arr[6] = 50;
console.log(arr);
console.log(arr[1]); //20
console.log(arr[2]); //undefined
// 获取数组的长度
console.log(arr.length);
// 修改length
arr.length = 10;
arr[arr.length] = 20;
//数组中的元素可以是任意的数据类型
arr = ['hello', 1, true, null, undefined];
// 也可以是对象
var obj = {
name: '丁小子'
};
arr[arr.length] = obj;
arr = [{
name: '丁'
}, {
name: '小'
}, {
name: '子'
}];
console.log(arr[1].name);
// 也可以是一个函数
arr = [function() {
alert(1)
}, function() {
alert(2)
}];
console.log(arr);
//数组中也可以放数组
arr = [
[1, 2, 3],
[3, 4, 5],
[6, 7, 8]
];
// push():在数组末尾添加一个或多个元素,并返回数组新的长度
// 可以将要添加的元素作为方法的参数传递
// 这样这些元素将会自动添加到数组末尾
arr.push('ddd', 'ccc');
console.log(arr);
var result = arr.push('1', '2');
console.log('result = ' + result);
// pop()从末尾删除,并返回这个被删除的
result = arr.pop();
console.log(result);
// unshift()
// 开头添加一个或多个元素,并返回新的数组长度
// 从前边插入后,其他元素索引会依次调整
arr.unshift('呆头');
console.log(arr); //和push相反从前面加
// Shift()可以删除数组第一个元素,并将删除的元素作为返回值。
// 遍历数组
for (var i = 0; i < 4; i++) {
console.log(arr[i]);
};
// js中还为我们提供了一个方法用来遍历数组:forEach()只支持IE8以上浏览器
// forEach()方法需要一个函数作为参数,像这种函数,由我们创建但是不由我们调用的,我们称为回调函数
// arr数组中有几个元素,函数就会执行几次,每次执行时,浏览器会将遍历到的元素
// 以实参的形式传递进来,我们可以来定义形参,来读取这些内容。
// 浏览器会在回调函数中传递三个参数
var arr = ['明', '天', '会', '更', '好'];
arr.forEach(function(a, b, c, d) {
console.log('a =' + a); //元素
console.log('b =' + b); //索引
console.log('c =' + c); //c == arr
console.log('d =' + d); //undefined
});
//slice()提前指定元素:参数:1.截取开始位置的索引2.截取结束位置的索引,第二个参数可以省略不写(该方法不会影响原数组,返回截取的)
// 索引可以传递负值,从后往前截取。
var arrnew = arr.slice(0, 2);
console.log(arrnew);
// splice()删除数组中的指定元素,会影响原数组,会将指定元素删除,并返回
// 参数:第一个表示开始位置的索引,第二个表示删除的数量,第三个及以后可以传递一些新的元素
var arrnew1 = arr.splice(0, 1, '每');
console.log(arrnew1);
console.log(arr);