对象
1内建对象
console string document
2 宿主对象js运行时的对象,浏览器提供的对象,DOM BOM
3 自定义对象 自己封装的对象
var a=1;
对象创建,
构造函数 new
使用字面量:手动声明,不是使用构造函数
一般在开发中,我们推荐大家使用[]方式来创建属性,这种方式更加的灵活
类型
简单类型(值类型)存储在栈
基本数据类型直接保存在栈内存中,值与值之间是独立的
引用类型(object) 存储在堆
对象保存在堆中,保存是对象的地址
函数
var func=function(){}
function say(){}
方法
如果一个函数作为一个对象的属性保存,那么此时叫做XXX对象的方法
var obj1={
name:"张三",
age:18,
todo:function(){
console.log("我吃的贼多,还不长肉");
}
}
返回值
js中所有的函数都有返回值
如果有返回结果那么需要写return
如果没有return 那么会返回一个undefined
注意:在JS中 形参的数量和实际传入的实参数量是可以不一致的
立即执行函数
//立即执行函数:函数定义完,就立刻被调用,这种函数只会执行一次。
//理解:立即执行函数并不是为了提高函数的复用性的,他是为后期我们编写异步程序准备的。
//匿名函数:函数没有名字
(function(n){
console.log(n);
})(10);
全局作用域
scope作用域:作用域值的是变量的作用范围
一、全局作用域:直接写在script标签的都是全局作用域,全局作用域中的变量在页面打开是创建,关闭时销毁
全局作用域变量全部都创建在window对象,通常情况下由于整个页面的所有元素都是window的,所以window是可以被省略的
二、函数作用域
变量声明提前:使用var声明对象,都会在代码执行前声明
this
/*
this:解析器(浏览器)在调用函数,每次都回给函数内部传递一个隐含的参数。
this指向一个对象,称为函数上下文对象。根据函数《调用方式》的不同,this会指向不同的对象。
调用方式:
1函数调用 此时this表示的是window
2方法调用 此时this表示的是obj这个对象
3构造函数调用 此时this代表新创建出来的对象
简单总结:如果用方法的形式调用函数的,那么可以通过this关键词来获取调用对象的属性信息
*/
//函数调用 此时this表示的是window
// function func1()
// {
// console.log(this);//未来调用我的对象
// console.log(this.name)
// }
// // func1();
// // //方法调用,此时this表示的是obj这个对象
// var obj1={
// name:"李四",
// say:func1
// }
// obj1.say();
// var obj2={
// name:"张三",
// say:func1
// }
// obj2.say();
//思考,如果没有this关键词会产生什么问题
var obj1={
name:"张三",
data:{name:"nihao"},
say:func1
}
var obj2={
name:"李四",
say:func1
}
var name="全局变量";
function func1()
{
console.log(this.data.name);
}
obj1.say();
obj2.say();
工厂模式创造对象
代码比较简单
但是没法区分对象的类型,全部都是object
function createObject(name,age,message){
var obj=new Object();
obj.name=name;
obj.age=age;
obj.say=function(){
console.log(message);
}
return obj;
}
构造函数
构造函数就是一个普通的函数,创建的方式和普通的函数没有任何区别
不同:
1.不同的是构造函数习惯首字母大写。
2.构造函数和普通函数调用的方式不同,构造函数调用使用new来调用的
总结:使用构造函数创建对象,是拥有自己的类型的,这样就解决了工厂创建对象的问题了。
使用构造函数形式创建对象,还是有问题?
*/
function Student(a,b,c){
this.name=a;
this.age=b;
this.gendar=c;
//公用方法
this.say=fun
}
function fun(){
console.log('我是一个学生');
}
var obj1=new Student("张三",18,'男');
console.log(obj1.say());
var obj2=new Student("李四",20,'女');
console.log(obj2.say());
//每一次创建一个对象 都会有一个独立的副本
console.log(obj1.say==obj2.say);
//如果每一个对象创建的时候都要去实例化公共方法 1W 1W 10W 10W 效率高?很低下
//如何解决:
//将函数作为全局作用域中的函数,这样每一个对象都是调用该函数
//问题:
//当全局作用域中的函数过多时,会导致全局作用域的污染。
//最终:原型属性 =>原型链
new
new到底做了什么?
1立即创建一个新对象
2将新建的对象设置为函数的this
3执行函数中的代码
4将对象返回
原型prototype
我们所创建的每一个函数,解析器都会向这个函数添加一个函数,这个属性叫prototype,这个属性对应一个对象,这个对象就是我们所说的原型对象
当函数以构造函数形式调用时,它所创建的对象中都有一个隐含属性,指向构造函数的原型对象,我们可以通过__proto__访问
function Person(){
//查找aaa属性,但是解析发现Person没有aaa属性,如果在函数中找不到相应的属性,那么会去他的原型中查找这个属性
//家里有车,你就开车,家里没车,你就去坐公交车
}
Person.prototype.aaa=103;
var obj=new Person();
obj.aaa="哈哈哈我是obj的aaa,我不是原型的aaa"
// console.log(Person.prototype);
// console.log(obj.__proto__);
// console.log(Person.prototype==obj.__proto__);
console.log(obj.aaa); //obj.__proto__.aaa
var obj1=new Person();
console.log(obj1.aaa);
function Student(a,b,c){
this.name=a;
this.age=b;
this.gendar=c;
}
Student.prototype.say=function(){
console.log('你好');
}
var s1=new Student();
var s2=new Student();
console.log(s1.say());
console.log(s2.say());
console.log(s1.say==s2.say)
原型作用
原型的用途:
1将对象中重复内容,放入原型中,这样所有对象都可以去访问调用,节省代码开支。 继承 封装
2可以修改js中原始的属性方法 多态
function Person(name)
{
this.name=name;
}
Person.prototype.aaa=123;
Person.prototype.toString=function(){
return "name="+this.name;
}
var obj=new Person('张三');
//检查一下obj的原型中有没有toString这个方法
//我们可以通过hasOwnProerty()来检查某一个属性是否在原型中存在
console.log(obj.__proto__.hasOwnProperty("toString"));
console.log(obj.__proto__.hasOwnProperty("aaa"));
//问题:obj中没有toString Person的原型属性中也没有toString 那么这个toString是哪来的?
console.log(obj.toString());
//Object生万物
console.log(obj.__proto__.__proto__);
数组
数组的常用方法:
-*push 数组最后添加一个元素
-pop 删除并返回数组的最后一个元素
-shift 删除并返回数组的第一个元素
-*join 数组的成员连接起来 注意:join得到的是一个字符串
-unshift 向数组的开头添加一个或更多元素,并返回新的长度
-*concat 连接两个或更多的数组,并返回结果
-reverse 数组元素翻转
-sort 排序
-*splice
--1起始位置 2删除长度 3要添加的元素
--删除元素: list.splice(1,2);
--替换元素: list.splice(1,2,10,10)
--插入元素: list.splice(1,0,'helloworld')
-slice 切片 截取 1开始位置 按照索引来的 2结束位置
-valueOf
**.forEach()**
*/
var list=[1,2,34,'a','A', 'z','B'];
arguments
调用函数的时候,浏览器每次会传递2个隐藏参数
1函数上下文对象this
2封装实参的对象,他是一个数组形式,在调用函数时,我们所传递的实参全部都在arguments
他虽然可以提供实参,但是在代码表述上,代码的编写上都不是很方便。
function test(name,age)
{
console.log(this);
console.log(arguments);
console.log(arguments[0]);
console.log(arguments[1])
}
test('张三',20);
call和apply
这两个方法是函数对象的方法,需要通过对象进行调用
当对函数对象调用这两个方法是,都会让函数立即执行
.call和()调用的区别是:
this的第四种用途:
1函数调用 此时this表示的是window
2方法调用 此时this表示的是obj这个对象
3构造函数调用 此时this代表新创建出来的对象
4在使用call和apply形式调用函数时,可以向其中传入任何一个对象,这个对象就会替代函数中的this
call和apply区别:
call是在传入对象后逐个传递参数,如果多个参数是用逗号分隔开的
apply是将参数以数组形式传递
function person(n1,n2,n3){
console.log(this);
console.log(n1)
console.log(n2);
}
// Person;//函数本身
// console.log(Person());
// Person();//调用
var obj={
name:"张三"
}
person.call(obj,2,3,"张三");
person.apply(obj,[2,3,"张三"]);
常用的宿主对象
字符串string
substring:进行字符串截取
参数1:=起始索引位置 包含当前索引的 必须的
参数2:结束的索引位置,不包含当前索引位置 可选的
如果没有结束位置,默认截到最后
slice:对字符串进行切片 位置是可以使用负数的
参数1:起始位置
参数2:结束位置
substr:进行字符串截取的
参数1:起始位置
参数2:长度 千万注意:是长度 不是结束的索引位置
*/
var name="Hello";
var name1="world";
console.log(name.charAt(3))
console.log(name.concat(name1));
console.log(name.substring(2,5));//llo <= <
console.log(name.slice(-2,-1));
console.log(name1.substr(3,2));// C# string.substring(3,2)
var date=new Date()
console.log(date.getYear());
定时函数
setInterval:1回调函数 2时间 毫秒为单位 周期性的调用
clearInterval(timer)
setTimeout只会运行依次
javascript中分为两种运行方式:
同步方式:
1按照代码的顺序依次执行。
2会阻塞进程
异步方式:
1不一定会按照代码的顺序依次执行
2不会阻塞程程
优点:1同时可以进行多任务的运行
缺点:1影响CPU运行
2程序结束时间是不可控制 回调函数
2分钟刷牙 2分钟洗脸 5分钟上厕所 煮水3分钟 吃面5分钟
同步:2+2+5+3+5=17分钟
异步:煮水3分钟
刷牙+洗脸4分钟 上厕所带吃面5 9分钟
ajax
var num=10
window.location=function(){
var time=setInterval(function(){
console.log(num);
num++;
if(num==20){
clearInterval(timer);
}
},10000)
}