复习:
以下类型都是 object
console.log(typeof new Object);
console.log(typeof new Array());
console.log(typeof new Date());
console.log(typeof new RegExp());
console.log(typeof new String());
console.log(typeof new Number());
console.log(typeof new Boolean());
console.log(typeof Math); // 就是一个对象 不能new
// 函数的类型是 function
console.log(typeof new Function());//function
typeof 6种类型 number string boolean undefined object function
in 运算符
作用:判断指定的属性是否存在于被检测的对象中(含自身属性和原型属性,无论普通 / 不可枚举 / 原型)
语法: key in obj
var obj = {
"name": "chuanchuan",
"age": 19,
"gender": "male"
};
// 遍历对象
for(var k in obj) {
console.log("key = " + k + ", v = " + obj[k]);//这里不能写obj.k;
}
console.log("age" in obj);// true
console.log("toString" in obj); // true toString 是继承来的
var arr = [1, 0];
// 对数组来说,索引就是数组的属性
console.log(2 in arr); // false 0和1在 2就不在了
// 判断是否存在属性的方法:
// 1 in
// var obj = {};
// console.log("age" in obj);
// 2 if
if(obj.age) {
// 如果有 。。。。
} else {
// 没有。。。
}
面试题
// 判断两个对象是否相等
console.log({} === {}); // false
console.log({} == {}); // false
console.log("1" == 1); // true
console.log("1" === 1); // false
// 值类型(简单类型)
// 如果存储的是数据本身,那么就是值类型5种
// 包括:string / number /boolean / null / undefined
// 引用类型(复杂类型)
// 如果存储的是数据的引用(地址),那么就是引用类型9种
// 包括:Object Function Array Date Math RegExp String Number Boolean
1. 为对象定义方法的两种方式
Product.prototype.buy=function(){};
Product.prototype={
buy:function(){}
}
2. 用构造函数创建属性的四种方式
/*传参形式*/
function Product(name){
this.name = name
}
Product.prototype={}
var iphone = new Product('iphone8s')
/*默认值*/
function Product(){
this.name = ''
this.price=0
}
Product.prototype={}
var iphone = new Product()
/*动态添加形式*/
iphone.description='XXXXXXXXXX'
iphone.images=[]
/*混合模式*/
function Product(name,price){
this.name = name
this.price=price
this.version=1.0
this.add=function(){}
}
Product.prototype={}
3. instanceof; A instanceof B 检测构造函数B的原型属性在不在A的原型链上
4. 两个面试题
①
var fun1 = function(){
this.name = 'peter';
return {
name: 'jack'
};
}
var p1 = new fun1();
console.log(p1.name)// jack
②
var fun2 = function(){
this.name = 'peter';
return 'jack';
}
var p2 = new fun2();
console.log(p2.name)//peter
③
var o = new Object();
// 2 创建一个函数
function foo(obj) {
obj.name = "腐女";
obj = new Object();
obj.name = "屌丝";
}
// 3 调用函数
foo(o);
console.log(o.name); //腐女
5. 函数声明和函数表达式的区别
var str =''
var num=1
var bool=true
var date = new Date()
console.log(fn()) //21行输出函数 本行输出undefined
console.log(fn2())// 报错 Uncaught TypeError: fn2 is not a function
//函数声明,变量fn以及其实现被提升到顶部
function fn(){
console.log('函数') //第21行
}
//函数表达式,仅变量fn2被提升到顶部,实现没有被提升
var fn2 = function(){
console.log('函数变量形式')
}
6. 属性的get和set
function Product(name,price) {
/*属性 行为 可以为空或者给默认值*/
this.name=name
this.price=1000;
this.description = '';
this.zhekou = ''
this.sales = ''
this.produceDate
//固定写法 写在构造函数内部 Object.defineProperty(this, "属性名", fn)
Object.defineProperty(this, "price", {
value:5000000,
writable: false, //设置属性是否可写
});
Object.defineProperty(this, "produceDate", {
get: function () {
return dateFormat(produceDate,'yyyy年MM月dd日');
},
set: function (value) {
produceDate = value;
}
});
}
7.公有属性 私有属性
function Person(name) {
//私有属性,只能在对象构造函数内部使用
var className = "用户对象";
//公有属性,在对象实例化后调用
this.name = name;
//私有方法
var privateFunction = function () {
alert(this.name);
}
//公有方法
this.publicFunction = function () {
alert(this.name); //公有属性
alert(className); //正确 直接通过变量名访问
alert(this.className); //undefined 错误 不能这样访问
}
//公有属性
alert(className);
//正确 直接通过变量名访问
alert(this.className); //undefined 错误 不能这样访问
}
8. 数据类型检测的方法
① typeOf(); 在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 “object”。
console.log(typeof undefined)//'undefined'
console.log(typeof null) //object 未知bug
console.log(typeof true) //'boolean'
console.log(typeof 123) //'number'
console.log(typeof "abc") //'string'
console.log(typeof function() {}) //'function'
var arr=[];
console.log(typeof {}) //'object'
console.log(typeof arr)//'object'
console.log(typeof unknownVariable) //'undefined'
②call方法 Object.prototype.toString.call()
console.log(toString.call(123)) // "[object Number]"
console.log(toString.call('123')) //"[object String]"
console.log(toString.call(undefined)) //"[object Undefined]"
console.log(toString.call(true)) //"[object Boolean]"
console.log(toString.call({})) //"[object Object]"
console.log(toString.call([])) //"[object Array]"
console.log(toString.call(function(){})) //"[object Function]"
③ instanceof
var arr = new Array()
console.log(arr instanceof Array) //---------------> true
console.log(date instanceof Date) //---------------> true
console.log(fn instanceof Function) //------------> true//
alert(f instanceof function) //------------> false
// 注意:instanceof 后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。
④ constructor 判断一个实例的构造函数是谁 对象.constructor
console.log(arr.constructor === Array) //----------> true
console.log(date.constructor === Date) //-----------> true
console.log(fn.constructor === Function) //-------> true
⑤jquery中的检测数据类型的方法
Query提供一系列工具方法,用来判断数据类型,以弥补JavaScript原生的typeof运算符的不足。
以下方法对参数进行判断,返回一个布尔值。
jQuery.isArray():是否为数组。
jQuery.isEmptyObject():是否为空对象(不含可枚举的属性)。
jQuery.isFunction():是否为函数。
jQuery.isNumeric():是否为数字。
jQuery.isPlainObject():是否为使用“{}”或“new Object”生成的对象,而不是浏览器原生提供的对象。
jQuery.isWindow():是否为window对象。
jQuery.isXMLDoc():判断一个DOM节点是否处于XML文档之中。
总和;
/判断变量是不是数值型/
//因为NaN也是number类型的,它是不能用于数值运算的。
function isNumber(val){
return typeof val === 'number' && isFinite(val);
}
// 顺便介绍一下JavaScript isFinite() 函数,isFinite() 函数用于检查其参数是否是有穷大,
// 如果 number 是有限数字(或可转换为有限数字),
// 那么返回 true。否则,如果 number 是 NaN(非数字),或者是正、负无穷大的数,则返回 false。
/*判断变量是不是布尔类型*/
function isBooleanType(val) {
return typeof val ==="boolean";
}
/*判断变量是不是字符串类型*/
function isStringType(val) {
return typeof val === "string";
}
/*判断变量是不是Undefined*/
function isUndefined(val) {
return typeof val === "undefined";
}
var a;//a是undefined
var s = "strType";
alert("变量a是Undefined的判断结果是:"+isUndefined(a));
alert("变量s是Undefined的判断结果是:"+isUndefined(s));
/*判断变量是不是对象*/
function isObj(str){
if(str && typeof str === 'object' && str.constructor!=Array){
return true;
}
return false
}
/*判断变量是不是null*/
function isNull(val){
return val === null;
}
/*判断变量是不是数组*/
//数组类型不可用typeof来判断。因为当变量是数组类型时,typeof会返回object。
//方法1
function isArray1(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}
//方法2
function isArray2(arr) {
if(arr === null || typeof arr === 'undefined'){
return false;
}
return arr.constructor === Array;
}
9. 基本数据类型 string number boolean
复杂数据类型(引用类型)
Array Date Object RegExp String Number Boolean function
值类型和引用类型
var obj = {
name : "宅男"
};
function jinhua(param){
//param = obj
param.name = "高富帅";
//下面的这句代码,重新创建了一个对象,修改了param的指向
//但是,obj还指向原来的那个对象 所以,在修改param的时候,修改的是
//新创建的对象,跟obj没有关系
param = {
name:"腐女"
};
param.name = "宅男";
}
jinhua(obj);
console.log(obj.name); //高富帅
//值类型做函数的参数
//函数内部的变量,也就是形参和实参只是简单的赋值操作,两个数据独立存储于内存中的
//在函数内部对形参进行修改,不会影响外面的变量
//引用类型做函数的参数
//还是把实参存储的地址赋值给了形参,在函数内部,形参同样也指向该对象,
//所以,在函数内部对该对象进行修改,会影响到外面的变量
//注意:如果在函数内部重新创建对象,为该形参赋值,那么两个对象将不再有关系
//修改其中一个,另外一个不受影响
10. delete关键字
var obj = {
name : "尼古拉斯@赵四",
age : 20
}
//delete关键字可以用来删除对象的属性或方法,删除未使用var声明的变量
//delete关键字有返回值 用来表示删除属性是否成功
//如果删除的是不存在的属性,返回值为true
//如果删除的属性存在原型当中,那么返回值为true,但是并未删除
示例:删除属性 本身有返回值
var obj = {age: 19};
console.log(obj.age); // 19
var b=delete obj.age;
console.log(b);//true
console.log(obj.age);//undefined
示例:删除变量
var num = 1;
// 没有用var声明的变量
num2 = 123;
var b1=delete num; // 使用var/let/const声明的变量是无法通过 delete 运算符删除的
var b2=delete num2; // 可以删除
console.log(b1)//false
console.log(b2)//true
console.log(num); // 1
console.log(num2); // 报错
示例:删除数组中的元素
// 删除数组中的元素
var arr = [1, 2];
delete arr[0];
console.log(arr); // [empty,2] length还是2
11. 异常捕获
//异常捕获语句的完整形式
try{
//可能出现异常的代码
xyz();
}
catch(e){
//出现异常后的处理代码 e就是异常信息
throw new Error("自定义信息");
//throw " 自定义信息";
}
finally{
console.log("我是finally中的代码");
//不管有没有出现异常,这里的代码都会执行
//node.js
//做释放资源的操作。
}
12. 创建对象的方式
① //1.对象字面量 var obj={key:value,key:value…}
//只能创建一次对象,复用性较差,如果要创建多个对象,代码冗余度太高
var obj = {
name:"演员",
singer:"薛段子手",
type:"流行"
};
var obj1 ={
name:"吻别",
singer:"张学友",
type:"流行"
}
②.使用内置构造函数
var obj = new Object();
obj.name = "一千个伤心的母牛";
obj.singer = "张学友";
obj.sing = function () {
console.log("一千个伤心的母牛");
}
var obj1 =new Object();
obj.name = "一千个伤心的母牛";
obj.singer = "张学友";
obj.sing = function () {
console.log("一千个伤心的母牛");
}
③.封装简单的工厂函数 (不推荐使用了)
function createSong(songName,singerName){
var o =new Object();
o.name = songName;
o.singer = singerName;
o.sing = function () {
console.log("让我来唱首歌");
}
return o;//{name:"",singer:"",sing:function...}
}
var obj = createSong("演员","薛之谦");
var obj1 = createSong("一言难尽","张宇");
④/自定义构造函数 Object Array
//什么是构造函数?
//构造函数其实也是函数,但是通常用来初始化对象
//并且和new关键字同时出现
//new 是用来创建对象的
//构造函数是用来初始化对象的(给对象新增成员)
//构造函数名,首字母要大写!!!以示区分
function Person() {
//默认隐含的操作,把刚才用new新创建出来的对象赋值给this
this.name = "尼古拉斯凯奇";
this.age = 50;
this.sayHello = function () {
console.log("Hey man");
}
//如果这里写其他的代码,会执行吗? 肯定会
return null;
}
var p = new Person();//new Object();
console.log(p);
p.sayHello();
*****构造函数的执行过程
1.使用new关键字创建对象
2.调用构造函数,把新创建出来的对象的引用赋值给构造函数内的this
3.在构造函数内使用this为新创建出来的对象新增成员
4.默认返回新创建的这个对象 (普通的函数,如果不写返回语句,会返回undefined)
*****构造函数的返回值
1.如果不写返回值,默认返回的是新创建出来的对象 (一般都不会去写这个return语句)
2.如果我们自己写return语句 return的是空值(return;)或者是基本类型的值或者null,都会默认返回新创建出来的对象
3.如果返回的是object类型的值,将不会返回刚才新创建的对象,取而代之的是return后面的值
13. 原型
原型:任何一个函数都有一个 prototype 的属性,函数的原型属性(prototype)的是 对象类型 的,由 构造函数 创建出来的对象,会默认链接到其构造函数的这个属性(prototype)上,构造函数的 prototype 属性的作用就是:实现数据共享
使用原型的注意事项
1.使用对象访问属性的时候,如果在本身内找不到就会去原型中查找,但是使用点语法进行属性赋值的时候,并不会去原型中进行查找,如果对象中不存在该属性,就会给该对象新增该属性,而不会去修改原型中的属性
2.如果在原型中的属性是引用类型的属性,
那么所有的对象共享该属性,并且一个对象修改了该引用类型属性中的成员,其他对象也都会受影响
3.一般情况下不会将属性放到原型对象中
一般情况下原型中只会放需要共享的方法
术语:F.prototype 原型属性
f.proto 原型对象
proto :每个对象都有一个__proto__属性,非标准,对象的 proto 与创建它的构造函数的 prototype 是一个东西
function F() {}
var o = new F();
console.log(o.__proto__ === F.prototype); //true
14. 创建函数的三种方式
创建函数的三种方式
1 函数声明的方式
2 函数表达式
3 通过 new Function() 创建 (后面单独详细介绍)
// 1
function foo1() {
function f() {}
}
// 2
var foo2 = function() {
};
// var foo2;
// foo2 = function() {};
// 3
var foo3 = new Function();
函数声明和函数表达式的区别
注意:预解析是带var的变量和函数体,而不带Var不会预解析,如果在赋值之前打印就报错 not defined;
1 函数表达式中的名字可以省略,如果没有省略,那么这个名字可以是任何的值,还有注意:这个名字只能函数体内部使用
2 提升
函数声明的方式,整个函数体都会被提升
函数表达式,提升的是变量
3 函数声明 不能出现在其他语句中
// 不推荐
/*if(true) {
function f() {console.log("11111");}
} else {
function f() {console.log("222222");}
}
f();*/
// 推荐使用这种方式
if(true) {
var f = function () {console.log("11111");}
} else {
var f = function () {console.log("222222");}
}
f();
15.面向对象和面向过程
面向过程:所有的细节、步骤、过程,要一步一步亲历亲为(执行者) 面向对象是对面向过程的封装
面向对象:找到能完成这个事情的对象,让它帮你完成就行(调度者)
// jQuery
// 面向对象的方式
$(“body”).append(“
jQuery创建节点就是如此潇洒
”);// js
// 面向过程的方式
var p = document.createElement("p");
var txt = document.createTextNode("creat E..,creat T..真麻烦");
p.appendChild(txt);
document.body.appendChild(p);
面向对象优势(解决函数封装问题)
封装代码,使代码更好维护
减少全局污染
将功能相近的代码组织到一起维护方便,找错方便
面向对象的基本模型
1 将数据与功能封装成函数(方法)
2 将相关的功能绑定到一起(对象)
3 将功能进行分组(模块)
16. 关于内存释放
17. 作用域练习题
题1
题2
18. 综合实战题
点击让数字加1 4种方法
上下两种一样的原理