JavaScript中的基本包装类型及函数的介绍
一.基本包装类型(三种)
1.Array.isArray()方法:
作用:判断某个对象是否是数组
判断对象的类型: typeof
==基本数据类型:==
- typeof 字符串 string
- typeof 数字 number
- typeof true|false boolean
- typeof null object
- typeof undefined undefined
==复杂数据类型==
- typeof 对象 object
- typeof 函数 function
Array.isArray()方法的实例:
eg:
<script>
var arr1 = [1,2,3];
console.log(typeof arr1);//object
var o = {};
console.log(typeof o);//object
//如何区分对象是数组还是Object类型的对象?
//构造器属性 并不严谨因为可以修改constructor属性
//arr1.constructor = Object;
console.log(arr1.constructor == Array);//true
console.log(o.constructor == Array);//false
//toString()方法 返回一个对象的字符串描述
var obj = {};
console.log(obj.toString());//[object Object] [对象类型 构造函数]
console.log(arr1.toString());//1,2,3 该方法被重写了
//Object.prototype
//技巧:获得对象的类型 call|apply
console.log(Object.prototype.toString.call(arr1));
console.log(Object.prototype.toString.call(function (){
}));//[object Function]
//兼容性处理
//判断该方法是否存在
if(typeof Array.isArray != 'function'){//不存在,自定义一个该方法
Array.isArray = function (obj){
return Object.prototype.toString.call(obj) == '[object Array]';
}
}
var str1 = new String('demo01');
var str2 = 'demo02';
console.log(Object.prototype.toString.call(str1));//[object String]
console.log(Object.prototype.toString.call(str2));//[object String] 问题:为什么str2不是对象却可以调用方法?
</script>
2.基本包装类型种类:
- String
- Number
- Boolean
==基本包装类型注意点:==
(1).基本包装类型的创建:
- 01 new String |Number | Boolean()
- 02 new Object() 参数(字符串|数值|布尔值)
- 03 Object ()
eg:
<script>
//01 创建字符串对象
var str1 = new String('string01');
var str2 = 'string01';
var str3 = String('string01');
var str4 = new Object('string01');
console.log(str4);//String
console.log(Object.prototype.toString.call(str4),'-----------');//[object String] ----------- 创建出来的是字符串对象[object String] 本身内部会做一个判断,如果是基本类型的值,就会自动转化为对应的基本包装类型
var str5 = Object('string01');
console.log(typeof str5,'+++++');//object 字符串对象
//02 创建数值对象
var num1 = new Number(1);
var num2 = 1;
//03 创建布尔类型的对象
var bool1 = new Boolean(0);
var bool2 = true;
console.log(typeof str1);//object
console.log(typeof num1);//object
console.log(typeof bool1);//object
console.log(typeof str2);//string
console.log(typeof num2);//number
console.log(typeof bool2);//boolean
console.log(bool1);//Boolean
console.log(str3);//string01
</script>
(2).比较(== | ===)的时候注意:
注意==先判断左右两边的类型是否相同,如果不同,那么可能存在隐式的类型转换基本包装类型的数据(基本类型的值),在访问属性或者是调用方法的时候,系统内部会先创建一个相对应的临时对象,通过这个对象来访问属性|调用方法,得到结果之后返回,然后直接销毁这个临时对象.
eg:
<script>
var str1 = new String('demo1');
//隐式转换:
//toString()方法 返回一个对象的字符串描述
//console.log(str1.toString());//demo1
var str2 = 'demo1';
var str3 = new String('demo1');
//比较(==)
console.log(str1 ==str2);//true[一个是对象另一个是基本数据类型,类型不一样所以在比较的时候会进行隐式的转换]
console.log(str1 ==str3);//false[两个都是对象,都是引用类型的数据,在比较的时候比较的是地址,因此不相等]
console.log(str1 === str2);//false 全等还需要判断类型
console.log(str1 === str3);//false
</script>
<script>
var str1 = 'sjfdkhdsklfls';
var str2 = new String('sdfjgkjgdl');
console.log(str1);
console.log(str2);
console.log(str1.length);//获得字符串的长度 13
//内部实现的过程
/*var temp = new String('sjfdkhdsklfls');
var result = temp.length;
str1.length = result;
temp = null;*/
console.log(str2.length);
console.log(str1.substr(1,2));
//字符串能够访问属性也能够调用方法,这是为什么呢?
//内部实现:
//基本包装类型的数据(基本类型的值),在访问属性或者是调用方法的时候,系统内部会先创建一个相对应的对象
//通过这个对象来访问属性|调用方法,得到结果之后返回,然后直接销毁这个临时对象
str1.name = '默认的名称';
console.log(str1.name);//undefined
</script>
补充:
++String()方法:++ 是把对象的值转换成字符串.
++Number的使用注意:++
需求:为所有的数值对象都添加一个方法(sum),在调用的时候内部使用当前的值和参数相加,并且返回
注意点: 扩展Number
01 变量.方法 成功
02 (数值).方法 成功 表达式
03 数值.方法 报错
eg:
<script>
Number.prototype.sum = function (a){
return this + a;
};
var num1 = 10;
var num2 = new Number(5);
console.log(num2.sum(1));//6
console.log(num1.sum(2));//12
console.log((10).sum(3));//13
//console.log(10.sum(3));//报错
</script>
==3.原型链的绘图==
eg:
<script>
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.showName = function (){
console.log(this.name);
};
Person.prototype.showAge = function (){
console.log(this.age);
};
function Boy(lol){
this.lol = lol;
}
//继承(原型链继承)
Boy.prototype = new Person();
var boy = new Boy('哈哈哈');
console.log(Person.prototype);//Object
console.log(Boy.constructor);//Function
console.log(Function.prototype);//function(){}
console.log(Function.__proto__);//function(){}
console.log(Function.prototype.constructor);//Function
console.log(Function.constructor);//Function
console.log(Function.__proto__.__proto__);//Object
console.log(Function.__proto__.__proto__ == Object.prototype);//true
console.log(Function.__proto__ == Function.constructor.prototype);//true
console.log(Function.__proto__ == Function.prototype);//true
</script>
二.Object.prototype详解
(1)Object.prototype详解:
01 constructor 构造器属性
- 原型对象 与之相关联的构造函数(实例属性|原型属性)
- 对象 创建该对象的构造函数
- 原型对象中的constructor属性指向的是对应的构造函数;实例对象中的constructor指向对应的构造函数,其中这里的constructor就是从原型中获取的.即:constructor是实例对象的原型对象的属性,而非实例属性
02 hasOwnProperty
- 检测是否有某个指定的属性(不包含原型属性)
- 对象.hasOwnProperty('属性)
03 isPrototypeOf | Object.getPrototypeOf (对象)
- 判断某个对象是否是指定对象的原型对象
eg:obj.isPrototypeOf(p1) - 注意点:在判断的时候会判断整条原型链
- isPrototypeOf: 是否是某个对象的原型对象
04 propertyIsEnumerable
- 检查某个属性是否可以枚举(列举) for...in
- 属性是可枚举|不可以枚举(自己设置)
05 toString()
作用:该方法返回一个对于该对象的字符串描述
- Object类型的对象 var o = {} 返回的是[object Object]
- 其他类型的对象: 数组|函数|String 返回的是字符串描述
- 注意点:和Number类型使用的时候,可以接受参数(几进制)
06 toLocalString
大部分情况同toString 会做本地化处理
07 valueOf
作用:获得对象的值
001 基本包装类型的对象(String |Number|Boolean),那么返回其对应的基本类型值
002 其他对象 返回的是对象本身
-
003 日期类型 Date 返回的是一个时间戳(1970).
eg:
<script> console.log(Object.prototype);//Object function Person(){ this.name = '默认' } var obj = {name:'lalala'}; Person.prototype = obj; var p1 = new Person(); console.log(obj.isPrototypeOf(p1));//true console.log(Object.prototype.isPrototypeOf(p1));//true console.log(p1.propertyIsEnumerable('name'));//true </script> <script> var arr1 = [1,2,3]; console.log(arr1.toString());//1,2,3 function func(){} console.log(func.toString());//function func(){} console.log('ssss'.toString());//ssss var num = new Number(13); console.log(num);//Number console.log(num.toString());//13 console.log(num.toString(2));//1101 console.log(num.toString(5));//23 var str1 = new String('demo1'); console.log(str1.valueOf());//demo1 console.log(typeof str1.valueOf());//string var obj = {age:30}; console.log(obj.valueOf());//Object var date = new Date(); console.log(date.valueOf());//1489501415780 </script>
(2).静态成员和实例成员:
静态成员:因为构造函数本身是函数,函数本质是对象,对象可以拥有属性和方法
直接添加在构造函数身上的属性和方法
实例成员:
构造函数创建的实例对象上面的属性和方法
原型成员:
构造函数的原型对象上面的属性和方法
eg:
<script>
function Person (){
this.name = '默认'
}
Person.prototype.hi = 'hi';
var p1 = new Person();
Person.des = 'des';
Person.desLog = function (){
console.log(this.des);
}
Person.desLog();//des
console.log(p1.name);//默认
console.log(p1.des);//undefined
console.log(p1.desLog);//undefined
// 不能获取构造函数身上的成员
console.log(p1.hi);//hi
</script>
(3).Object的静态成员的详解:
==静态成员:==
01 Object.apply
作用:借用其他对象的方法
用法:对象.方法.apply(this绑定的对象,[参数1,参数2])
02 Object.arguments
函数内部的一个隐藏参数,这个隐藏参数用来接收实参的
它本身是一个类似于数组的结构,但是并不是数组,他可以想数组一样通过下标操作数据
03 Object.assign
作用:拷贝对象的属性,多个对象,但是不拷贝其原型对象,将返回目标对象
04 Object.bind
该方法的作用同call|apply差不多
05 Object.call
作用:借用其他对象的方法
用法:对象.方法.call(this绑定的对象,参数1,参数2)
06 Object.caller
指向调用当前函数的函数
07 Object.create
创建对象,并设置原型对象
08 Object,getOwnPropertyDescriptor
作用:获得某个属性的实例属性的描述信息(对象)
描述对象:
01是否可以配置 configurable
如果是true该属性可以被删除,且configurable可以被设置为false如果是false该属性不可以被删除,且configurable不可以再被设置为true02 是否可以枚举 enumerable
如果是true,那么在使用for...in循环遍历对象的时候可以列举出来,否则不可以列举03 是否可以重写 writable
修改这个属性的值04 具体的值 value
09 Object.getOwnPropertyDescriptors
作用:多个属性的描述信息(对象)
10 Object.definedProperty
作用:设置对象中的某个属性的描述信息(对象)
11.Object.getOwnPropertyNames
返回对象中所有实例属性的名称数组
关于是否可以枚举 不论是否可以被枚举都会返回
12.Object.keys
返回对象中所有实例属性的名称数组 只返回可以被枚举的属性
13.Object.getPrototypeOf
获得某个对象的原型对象
14.Object.preventExtensions
作用:禁止扩展对象 不能添加任何的属性和方法
15.Object.seal
作用:密封(封闭对象)
特征:不能够扩展对象 也不能删除对象的属性
16.Object.freeze
作用:冻结对象
特征:不能够扩展对象,也不能删除对象,也不能修改对象
eg:
<script>
var o = {name:'张三'};
Object.freeze(o);//密封
delete o.name;
console.log(o,'****');//删不掉
o.age = 33;
console.log(o,'$$$$$$$$$$$$$$');//添加不了
o.name = '张老汉';
console.log(o.name);//修改不了
</script>
<script>
var o = {};
o.name = '李四';
console.log(o);
Object.defineProperty(o,'name',{
configurable:true, //如果是false,那么无法删除成功
enumerable:false,//不可以枚举
writable:true,
value:"李四"
});
console.log(Object.getOwnPropertyNames(o),'########');//有一个是不可枚举的
console.log(Object.keys(o),'$$');//返回的是0个枚举的
</script>
<script>
function Person(){
this.name = '默认';
}
Person.prototype.des = '默认的描述信息';
var p1 = new Person();
console.log(Object.keys(p1));
</script>
<script>
var o = {name:'张三',age:99};
Object.defineProperty(o,'name',{
configurable:true, //如果是false,那么无法删除成功
enumerable:true,
writable:false,
value:"李四"
});
console.log(o.name);//李四
//01是否删除
delete o.name;
console.log(o.name);//undefined
//02是否可以被枚举
for(var k in o){
console.log('_________',k,o[k]);//age 99
}
//03是否可以被重写(属性是否可以被修改)
console.log(o.name);//undefined
o.name = '老王';
console.log(o.name);//老王
console.log(Object.getOwnPropertyNames(o));//age name
</script>
三.函数的介绍
1. 函数的创建方法(3种):
(1).函数的声明
格式: function 函数的名称(参数1,参数2....){函数体}
(2).函数的表达式
格式: var 变量名 = function [函数可以省略](){函数体}
- 如果有函数名称,那么就是命名函数表达式
- 如果函数名称省略,那么就是匿名函数表达式
(3).使用Function构造函数来创建
格式: var 变量名 = new Function(参数)
2. 使用构造函数创建对象 参数:
类型:字符串 转义字符 \ 加在 '之前
参数说明:
如果没有参数:那么就是一个空函数
如果有一个参数:那么这个参数就作为新创建出来的函数的函数体
如果有多个参数:那么最后一个参数作为函数的函数体,前面的参数全部都是形参
3. 处理参数过长问题(三种方式)
001 + 拼接
002 模板
003 `` ESC下面这个键
eg:
<script>
/* console.log("听说白雪公主在逃跑");
console.log("小红帽在担心大灰狼");
console.log("听说疯帽爱着爱丽丝");
console.log("丑小鸭会变成白天鹅");*/
//001 + 拼接
var logDemo = new Function("console.log(\"听说白雪公主在逃跑\");" +
"console.log(\"小红帽在担心大灰狼\");" +
"console.log(\"听说疯帽爱着爱丽丝\");" +
"console.log(\"丑小鸭会变成白天鹅\");");
logDemo();
</script>
//002 模板
<script type-="text/template" id="demo">
console.log("听说白雪公主在逃跑");
console.log("小红帽在担心大灰狼");
console.log("听说疯帽爱着爱丽丝");
console.log("丑小鸭会变成白天鹅");
</script>
<script>
var scr = document.getElementById('demo');
var str = scr.innerText;
var fooDemo02 = new Function(str);
fooDemo02();
console.log('++++++++++++');
</script>
#使用新特性来处理
<script>
var fool03 = new Function(`console.log("听说白雪公主在逃跑");
console.log("小红帽在担心大灰狼");
console.log("听说疯帽爱着爱丽丝");
console.log("丑小鸭会变成白天鹅");`);
fool03();
console.log('$$$$$$$$$$$$');
</script>
<script>
//01 函数的声明
function func(a,b){
//函数体
console.log('你好');
console.log(a+b);
}
//02 函数的表达式
var func02 = function (){
//函数体 匿名函数
}
var func02 = function name() {
//函数体
}
//03 使用Function构造函数来创建
var func03 = new Function();
func03();
</script>
<script>
var foo = new Function('console.log(\'你好\');');
foo();
var fool = new Function('a','b','return a+ b;');
console.log(fool(1,22));
</script>
4.arguments和length的用法
函数内部有两个隐藏的参数:arguments和length
- ==arguments==:类似于数组的结构(不是数组),用来接收实参
- 01 实参的数量小于形参的数量 不足的为undefined
- 02 实参的数量大于形参的数量 超出的部分会忽略在函数内部要获得超出的部分,利用arguments来获取;
- ==length属性==:
arguments.length 实际参数的长度
-
函数名.length 形式参数的长度
eg: <script> function foo(a,b){ console.log(arguments.length);//5 } console.log(foo.length);//2 foo(1,2,3,4,5); </script> <script> function func(a,b){ this.name = 'hahaha'; console.log(arguments);//Arguments[3] console.log(a);//1 console.log(b);//2 console.log(this);//window console.log(arguments[func.length]);//3 } func(1,2,3); var o = {}; o.show = func; o.show('demo01','demo02'); var test = new func(); </script>
5.callee和caller的使用说明
==callee :==指向的是函数自己,主要用于匿名函数的递归操作
==caller :==指向的是调用当前函数的函数 补充说明:如果直接调用函数,那么指向的并不是window而是null;
==递归:==
01自己调用自己
-
02 要有结束条件
eg: 0~1 0 + 1; 0~2 0 + 1 + 2; 0~3 0 + 1 + 2 + 3; 0~4 0 + 1 + 2 + 3 + 4; 0~N 转换为 0~(N-1) + N <script> function demo(n){ if(n == 1){ return 1; } return demo(n-1) +n; } </script> <script> var result = (function (n){ if(n == 1){ return 1; } return arguments.callee(n-1) + n; })(234); console.log(result); </script> <script> function fool1(){ console.log(fool1.caller); } function foo02(){ fool1(); } foo02(); window.fool1();//null </script>
6.Function的应用(去重和求最大值)
eg:
<script>
var arrayM = [1,2,3,4];
console.log(arrayM.indexOf(4));//3
console.log(arrayM.indexOf(5));//-1
// indexOf():用来获取某个元素的位置,返回的是当前数据在数组中的索引
//如果该元素不存在,则返回为-1;
</script>
01 数组去重
<script>
function test(){
//01 初始化一个空数组
var arr = [];
//02 遍历用户传入的所有数据
for(var i = 0;i<arguments.length;i++){
//03 判断数组中是否存在当前元素,如果没有那么就添加
if(arr.indexOf(arguments[i]) == -1){
arr.push(arguments[i]);
}
}
return arr;
}
console.log(test(1, 2, 3, 4, 5, 4, 3, 2, 1, 5, 6, 7, 3, 42, 1));
</script>
02 求取最大值
<script>
function getMaxNumber(){
var maxNum = arguments[0];
for (var i=0;i<arguments.length;i++){
if(maxNum < arguments[i]){
maxNum = arguments[i];
}
}
return maxNum;
}
console.log(getMaxNumber(1,23,4545,655));
</script>
7.eval的简单的用法
eval: 把字符串转换js的代码,并且(马上执行)
-
Function: 把字符串转化为js的代码并且(函数调用的时候)执行
eg: <script> eval('var a = \'test\''); console.log(a);//test </script>
注意点:
使用eval来转换json--->对象
方法:
01 在前面拼接一个对象声明
02 把json字符串包装成一个表达式
==补充:JSON转换(eval)==
JSON:一种通用的轻量级的数据结构,用来表示数据|传输数据
XML:体积大
JSON数据和字面量对象的对比:
01 json本质上是字符串,是一种有格式的字符串
标准的json它的key要求加双引号,json没有方法(函数)02 js中的对象是Object类型
JSON解析操作:
01 把JSON字符串转换为js的对象
02 把对象转换为JSON字符串
eg:
<script>
var json = "{\"name\":\"张三\"}";
console.log(json);
//JSON
var o = JSON.parse(json);
console.log(o);
var obj = {name:"李四",age:99};
var jsonStr = JSON.stringify(obj);
console.log(jsonStr);
//使用eval来转换json--->对象
//01 在前面拼接一个对象声明
//02 把json字符串包装成一个表达式
eval("var jsonObj = " + jsonStr);
console.log(jsonObj);
var objTest = eval("(" + jsonStr + ")");
console.log(objTest);
</script>
<script>
var json = '{\'name\':\'张三\'}';
console.log(json);
//JSON
var o = JSON.parse(json);
console.log(o);//{'name':'张三'}
var obj = {name:'李四',age:99};
var jsonStr = JSON.stringify(obj);
console.log(jsonStr);
//使用eval来转换json--->对象
//方法:
//01 在前面拼接一个对象声明
//02 把json字符串包装成一个表达式
eval('var jsonObj = ' +jsonStr);
console.log(jsonObj);
var objTest = eval('('+jsonStr+')');
console.log(objTest);
</script
8.Function.prototype原型链
- 001 Function.prototype ==>空函数
- 002 Function.constructor = Function
- 003 Function.proto == Function.prototype ==>空函数
- 004 空函数.proto.proto == Object.prototype
==Function和Object关系:==
互为对方的实例对象,全部都是true
eg:
<script>
//instanceof:判断某个对象是否是指定构造函数的实例对象
console.log(Function instanceof Function);//true
console.log(Object instanceof Object);//true
console.log(Function instanceof Object);//true
console.log(Object instanceof Function);//true
</script>
<script>
console.log(Object.__proto__);//空函数
console.log(Object.prototype.constructor == Object);//true
</script>
<script>
console.log(Object.__proto__);//空函数
console.log(Object.prototype.constructor == Object);//true
</script>
9.私有变量和私有函数
私有变量和函数:
定义在构造函数内部而被this对象访问的变量,在外部无法访问到的变量和函数
公有变量和方法:
对外暴露接口,可以通过构造函数对象创建的对象访问的属性和方法
eg:<script>
function Car(type,number){
this.type = type;
this.number = number;
var city = '厦门';//私有变量
var getNumber = function (){//私有函数
return number;
};
var getType = function (){//私有函数
return type;
};
//能够访问私有变量和函数的方法 ---特权方法
this.getDescription = function (){
console.log(getNumber() +getType() +city);
}
}
var car = new Car('汽车','201712');
car.getDescription();
</script>
eg2:
<script>
function Person(name){
this.name = name;
//在构造函数内部可以随便写代码
var a = 'testA';
function showA() {
console.log(a);
}
//像这样的本身是实例对象上面的方法,在方法内部可以访问私有变量或者是私有函数,这种方法称为特权法
this.test = function (){
showA();
console.log(a);
}
}
var p1 = new Person();
console.log(p1.a);//undefined
p1.test();//testA testA
</script>
10.with的简单说明
==with作用:== 把对象的作用域延伸到{}中,主要用于缩减代码 对象.属性.属性.属性
在{}中可以通过无前缀的方式来设置属性的值
注意点:
01this指向window
02 如果是添加属性,那么必须要使用前缀
-
03 严格模式下被禁止使用
eg:
<script> var obj = { name:'张三', age:23 } with(obj){ name:'李四'; age:99; console.log(this);//window obj.des = 'des'; //如果是添加属性,那么必须要使用前缀 } console.log(obj); console.log(des); </script> <script> //01 获取元素 var div = document.getElementsByTagName('div'); //02设置样式 with(div.style){ height:'100px'; width:'300px'; background:'red'; border:'1px solid #ccc'; } (function (t){ t.height = '100px'; t.width = '300px'; t.background = 'red'; t.border = '1px solid #ccc'; })(div.style); //获取元素 var div1 = document.getElementById('demo'); var getEle = document.getElementById; var div1 = getEle("demo"); //? 为什么不能这样写 </script>