Array.isArray()
- 作用:判断某个对象是否是数组
- 使用:
Array.isArray(对象)
返回值:布尔类型的值(true|false) - 注意点:
兼容性问题(ES5) - 思考:
如何判断某个对象是否是一个数组
typeof 关键字用于判断数据的类型(基本数据类型 + 复杂数据类型) - 基本数据类型
typeof 字符串 string
typeof 数字 number
typeof true|flase boolean
typeof null object(!)
typeof undefined undefined - 复杂数据类型
typeof 对象类型 object
typeof 函数类型 function - 实现思路:
- 判断这个对象是否有特定的方法(push) 可以实现但是不严谨 不推荐
- instanceOf 似乎可以
- 判断对象的构造器属性 可以实现,但是不严谨
- toString 方法
- 在使用[]语法设置对象的时候
[]中存放的是字符串,那么这个字符串就直接作为 key
[]中存放的不是字符串,那么就把[]中部分当成一个变量来处理,查找最近变量,获取其值
如果对应的值是字符串,那么就直接作为 key
如果对应的值是对象,那么就尝试把这个对象转换为字符串(toString) - toString:
返回的是对当前对象的字符串描述
object 类型对象的 toString: Object.prototye
数组类型 toString:Array.prototype - 对象在作为 key 的时候
如何判断数组
如何判断日期类型
var o = {};
var a ={};
var b = {name:"张三"};
o["a"] = "Test-a";
o["b"] = "Test-b";
o[b] = "Demo-b";
o[a] = "Demo-a";
console.log(o.a); //Demo-a Test-a
console.log(o.b); //Test-b Test-b
console.log(o[a]); //Demo-a Demo-b
console.log(o[b]); //Demo-b Demo-b
console.log(o["a"]); //Test-a Test-a
console.log(o["b"]); //Demo-b Test-b
var arr1= [1,2,3];
console.log( arr1.toString());
var func = function () {
}
console.log(typeof func.toString());
console.log(a.toString()); //[object Object] [类型 构造函数]
console.log(b.toString());
console.log(o);
if (typeof Array.isArray != "function")
{
Array.isArray = function (obj) {
return Object.prototype.toString.call(obj) == "[object Array]";
}
}
var arr = [1,2,3];
console.log(Array.isArray(arr));
</script>
<script>
var arr1 = [1,2,3];
console.log(Object.prototype.toString.call(arr1)); //[object Array]
var date = new Date();
console.log(typeof date);
console.log(Object.prototype.toString.call(function () {
}));
</script>
<script>
function Person() {
}
Person.show = function () {
console.log("Person");
}
function Boy() {
}
Boy.prototype = new Person();
Boy.prototype.show = function () {
console.log("Boy");
}
var boy = new Boy();
boy.show(); //Boy
instanceOf 补充
- 错误描述
检查某个对象是否由指定构造函数创建出来的 - 正确描述
检查该对象的构造函数的原型对象是否在当前对象的原型链上面,如果在那么结果为 true ,如果不在那么结果为 false
function Person() {
}
function Dog() {
}
var p1 = new Person();
console.log(p1 instanceof Person); //true
console.log(p1 instanceof Dog); //fasle
console.log(p1 instanceof Object); //true
function Person() {
}
var p1 = new Person();
console.log(p1 instanceof Person); //true
Person.prototype = {}
console.log(p1 instanceof Person); //false
基本包装类型
- String\Boolean\Number
- 基本包装类型如何创建对象
字符串对象|数值对象|布尔累心的对象 - new String|Number|Boolean()
- new Object('字符串'|数值|[true|false])
- Object('字符串'|数值|[true|false])
注意点
直接使用构造函数()方式创建的并非对应的对象而是基本数据类型的值
var str1 = new String("demo01");
var str2 = "demo01";
var str3 = new Object("demo01");
var str4 = Object("demo01");
var str5 = String("demo01"); //字符串还是字符串对象?
console.log(typeof str1, typeof str2,typeof str3,typeof str4);
console.log(typeof str5);
var num1 = new Number(1);
var num2 = 1;
var num3 = new Object(1);
console.log(typeof num1, typeof num2,typeof num3);
var bool1 = new Boolean(true);
var bool2 = true;
console.log(typeof bool1, typeof bool2);
基本数据类型的使用注意
- 关于比较(==等于)||(===全等于)
- 思考:只有对象才可以访问属性和方法,为什么普通字符串也可以?
- 内部实现细节
当我们基本数据类型的值(字符串|数值)在访问属性或者是调用方法的时候 - 会先创建一个与之相对应的对象
- 使用该对象来访问属性或者是调用方法
- 得到一个结果并且返回
- 把临时创建的对象销毁
var str1 = new String("demo01"); //ox11
var str2 = "demo01";
var str3 = new Object("demo01"); //0x22
var str4 = Object("demo01");
var str5 = String("demo01"); //字符串还是字符串对象?
var str6 = "demo01";
console.log(str2 == str6); //true 两个都是基本类型的值在比较的时候比较内容(demo01)
console.log(str1 == str2); //true 类型不一样,内部有隐式的转换(对象.valueOf)
console.log(str1 == str3); //false
console.log(typeof str1, typeof str2,typeof str3,typeof str4);
console.log(typeof str5);
var num1 = new Number(1);
var num2 = 1;
var num3 = new Object(1);
console.log(typeof num1, typeof num2,typeof num3);
var bool1 = new Boolean(true);
var bool2 = true;
console.log(typeof bool1, typeof bool2);
var str01 = "string01";
console.log(str01.length); //8
//var tmp = new String(str01);
//tmp.length ==>8
//tmp = null;
console.log(str01.substr(1, 2)); //tr
var str02 = new String("sting02");
str02.name = "默认的name";
console.log(str02.name); //默认的name
str01.name = "测试的名称";
console.log(str01.name); //undefined
Number 的使用注意
- 需求:给所有的数值添加一个 sum 方法,该方法接收一个参数,返回当前参数和这个参数的和
Number.prototype.sum = funciton(n){
return n + this;
}
var num1 = new Number(10);
console.log(num1.sum(20)); //30
var num2 = 11;
console.log(num2.sum(10)); //21
//console.log(10.sum(5)) 错误调用
console.log((10).sum(5)) //表达式加上一个括号
原型链绘图
- 复杂原型链
- 构造函数本身是函数,函数本质上是对象,因此函数也有构造函数,即构造函数也有自己IDE构造函数
Boy.constructor ==Function
- Function 的原型对象是一个空函数
Function.prototype == 空函数(function(){})
- Function 本身是构造函数,所以它也有自己的构造函数
Function.constructor == Function
- Function 对象的原型对象应该是它的构造函数的原型对象
Function.__proto__ ==Function.constructor.prototype == Function.prototype == 空函数
- Object 本身是一个构造函数,因此也有自己IDE构造函数
Object.constructor == Function
- Object 的原型对象爱过你应该是它的构造函数的原型对象
Object.__proto__ ==Object.consructor.prototype ==Function.prototype == 空函数
- 推论:
空函数的原型对象应该是它的构造函数的原型对象
空函数.__proto__ == 空函数.constructor.porotype == Function.prototype == 空函数
?错误
正确:空函数.proto ==Object.prototype
function Person() {}
function Boy() {}
Boy.prototype = new Person(); //实现原型链继承
Boy.prototype.constructor = Boy;
var boy = new Boy();
console.log(Boy.constructor == Function);
console.log(Boy.constructor.prototype == Function.prototype);
console.log(Function.prototype );
console.log(Boy.__proto__ == Function.prototype);
console.log(Boy.__proto__);
console.log(Function.constructor == Function);
console.log(Object.constructor == Function);
console.log(Function.prototype.__proto__ == Function.prototype.constructor.prototype);
console.log(Function.prototype.__proto__ == Object.prototype);
Object 和 Function 的关系
- instanceOf
构造函数的原型对象是否在当前对象的原型链中
console.log(Object instanceof Object);
// 构造函数(Object)的原型对象(Object.prototype)是否在当前对象(Object)的原型链中
console.log(Function instanceof Function);
// 构造函数(Function)的原型对象(空函数)是否在当前对象(Function)的原型链中
console.log(Function instanceof Object);
//构造函数(Object)的原型对象(Object.prototype)是否在当前对象(Function)的原型链中
console.log(Object instanceof Function);
// Function的原型对象(空函数)是否在Object的原型链中
Object.prototype 详解
- constructor
构造器属性:指向的构造函数
对象.constructor 该属性不是这个对象的实例属性,是它原型对象上面的属性,指向的是创建该对象的构造函数
原型对象.constructor 该属性是这个对象的实例属性,指向的是相关联的构造函数 - hasOwnProperty
检查对象中是否存在某个指定的成员(仅仅检查实例属性) - isPrototypeOf
作用:判断对象是否是另一个对象的原型对象
原型对象.isPrototypeOf(对象)
注意点:检查整条原型链
function Person(){
this.name = 'haha';
}
var p1 = new Person();
console.log(Person.prototype.isPrototypeOf(p1));
var o = {};
console.log(o.isPrototypeOf(p1));
console.log(Object.prototype.isPrototypeOf(p1));
console.log(p1.propertyIsEnumerAble("age"));
- prototypeIsEnumerable
检查对象的属性是否是可以被枚举的(列举)
如果是可以枚举的,那么再使用 for...in循环遍历的时候,会打印 - toLocaleString
返回的是一个本地化字符串描述信息,大部分情况下同 toString 方法 - toString
如果是 object 类型的对象,返回的是[object Object]
如果是其他类型的对象,返回的是对应的字符串描述
如果是 Number 类型调用,那么可以接收一个参数(几进制),如果不传参那么默认的是十进制
console.log(typeof (10).toString());
console.log((10).toString(2)); //1010 1*2*2*2 + 0 *2*2 +1*2 +0*1 = 10
console.log((10).toString(3)); //101 1 * 3* 3 + 0 *3 + 1 = 10
- valueOf
获得这个对象对应的值
如果是基本包装类型,返回对应的基本类型之
如果是其他的对象,返回的是这个对象本身
如果是日期类型的对象,返回的是时间戳
var str1 = new String("demo01");
console.log(typeof str1.valueOf()); //demo01
var num1 = new Number(10);
console.log(typeof num1.valueOf()); //number 10
var o = {name:"张三"};
console.log(o.valueOf());
var date = new Date();
console.log(date.valueOf());
静态成员和实例成员
- 成员:属性 + 方法
- 实例成员:
对象自己的属性和方法 - 原型成员
对象的原型对象上面的属性和方法 - 静态成员
直接把属性或者是方法写在构造函数身上
function Person() {
this.name = "默认"
}
Person.prototype.showName = function () {
console.log(this.name);
}
var p1 = new Person();
Person.des = "默认的描述信息";
Person.showDes = function () {
console.log(this.des);
}
Person.showDes();
Object 的静态成员
- Object.apply
借用其他对象的方法
使用
对象1.方法.apply(对象2,[参数1,参数2...]) - Object.arguments
这是一个隐藏的参数,在函数中使用
用来接收函数调用时候传入的实参 - Object.assign
拷贝属性,特点(一次性拷贝多个对象的属性)
Object.assign(目标对象,要拷贝属性的对象1,要拷贝属性的对象2...) - Object.call
同 apply
对象1.方法.call(对象2,参数1,参数2...) - Object.caller
谁调用当前的方法,那么就指向谁 - Object.create
创建对象并且是该对象的原型对象
Object.create(要设置为新对象的原型对象)
funciton f1(){
f2();
}
function f2(){
console.log(f2.caller);
}
f1();
var o ={name:'张三'};
var obj = Object.create(o);
console.log(obj);
- Object.getOwnPropertyDescriptor
获取对象中某个属性的描述信息(描述对象)
属性的描述信息: - 该属性对应的值
- 该属性是否是可枚举的 enumerable for .. in 列举
- 该属性是否是可配置的 configurable
如果是可配置的 该属性可以被删除,并且可以被修改为不可配置的
如果是不可配置的 该属性不可以被删除,并且不可以被修改为可配置的 - 该属性是否是可重写的 writable
该属性是否可以被修改 - Object.getOwnPropertyDescriptors
获得对象中多个户型的描述信息
var o = {
name:'张三',
age:20
}
console.log(Object.getOwnPropertyDescriptor(o,'name'));
console.log(Object.getOwnPropertyDescriptors(o,'name','age'));
- Object.defineProperty
用来设置度喜爱功能中某个属性的描述信息(对象)
参数:
第一个参数:对象
第二个参数:属性
第三个参数:描述对象
注意点:
如果是已经存在的属性,在设置的时候,如果我们省略不谢,那么默认值全是 true
如果是新增加一个属性,在设置的时候,如果我们省略不谢,那么默认值全都是 false
var o = {
name:"张三",
des:"描述信息"
}
console.log(Object.getOwnPropertyDescriptor(o, "name"));
//
Object.defineProperty(o, "name",{
configurable:true, //删除属性,以及配置
writable:true, //重写属性 修改
enumerable:false,
value:"张三"
});
// console.log(o.name);
// console.log(delete o.name);
// console.log(o.name);
console.log(o.name);
o.name = "李四";
console.log(o.name);
for (var i in o)
{
console.log(i, o[i]);
}
Object.defineProperty(o, "des",{
configurable:false, //删除属性,以及配置
value:"描述信息"
});
//在设置的时候,如果我们省略不写,那么默认值是什么? 全部都是true
console.log(Object.getOwnPropertyDescriptor(o, "des"));
//新增加一个age属性并且设置描述对象
Object.defineProperty(o, "age",{
configurable:true, //删除属性,以及配置
value:20
});
console.log(Object.getOwnPropertyDescriptor(o, "age"));
- Object.getOwnPropertyNames
获得对象所有的实例属性名(key),返回值是一个数组
不论该属性是否是可枚举的,都可以获取
var o = {
name:"哈哈",
showName:function () {
} console.log(Object.getOwnPropertyNames(o));
- Object.keys
获取所有的 key
思考:包含原型对象的成员吗?不包含
区别:该方法在获取 key 的时候会检查是否是可枚举的,只能获取可枚举的 key
function Person() {
this.name = "默认";
this.age = 20;
}
Person.prototype.hi = "hi";
var p1 = new Person();
Object.defineProperty(p1, "name",{
enumerable:false,
value:"李四"
})
console.log(Object.keys(p1));
console.log(Object.getOwnPropertyNames(p1)); console.log(Object.getPrototypeOf(p1));
- Object.getPrototypeOf
获取原型对象
Object.preventExtensios|Object.isExtensible
禁止对象扩展(不能给对象添加属性或者是方法)
- Object.seal
密封对象(对象不能添加成员 + 不能删除成员) - Object.freeze
冻结对象(对象不能添加成员 + 不能删除成员 + 不能修改成员)
var o = {};
o.name = "张三";
console.log(o.name);
// Object.preventExtensions(o);
o.age = 20;
console.log(o.age);
// console.log(Object.isExtensible(o));
Object.freeze(o);
o.des = "hahah";
console.log(o.des);
delete o.name;
console.log(o.name);
o.name = "李四";
console.log(o.name);
Function 构造函数的使用
- 函数的几种创建方式
- 函数声明 function 名称(参数){函数体}
- 函数表达式
var func = function 名称(参数){函数体}
var func = function 名称(参数){函数体} 命名函数表达式
var func = function (参数){函数体} 匿名函数表达式
(function(){})() 即时函数 (闭包)
- 使用构造函数来创建 Function
- 使用 Function 来创建函数
参数:
最后一个参数:是新创建函数的函数体
其他参数:作为新函数的形参 - 需求
解决参数过长问题: - +号方式链接
- `` ESC 下面的案件
- 使用模版
var func = new Function();
// console.log(func);
function sum(a,b) {
return a + b;
}
console.log(sum(1, 2));
var demo = new Function("a","b","return a + b;");
console.log(demo(1, 6));
var demo1 = new Function("console.log(\"你是天边最美的云彩\");");
demo1();
console.log("听说白雪公主在逃跑");
console.log("小红帽在担心大灰狼");
console.log("听说风帽爱着爱丽丝");
console.log("丑小鸭会变成白天鹅");
console.log("____________");
var func01 = new Function("console.log(\"听说白雪公主在逃跑\");" +
"console.log(\"小红帽在担心大灰狼\");" +
"console.log(\"听说风帽爱着爱丽丝\");" +
"console.log(\"丑小鸭会变成白天鹅\");");
func01();
var func02 = new Function(`console.log("听说白雪公主在逃跑");
console.log("小红帽在担心大灰狼");
console.log("听说风帽爱着爱丽丝");
console.log("丑小鸭会变成白天鹅");`);
func02();
//01 获得标签
var scriptT = document.getElementById("demo");
//02 获得内容
var func03 = new Function(scriptT.innerText);
console.log("++++++++++++++++++");
func03();
arguments.length
- 函数内部的隐藏参数
this this 指向的是一个对象
说明 函数的调用方式会影响到函数内部 this 的指向 - 对象.方法 以对象的方法来进行调用 this->对象本身
- 以普通函数方式进行调用 this ->window(非严格模式)
- 以构造函数的方式来调用 this->新创建的对象
- 函数上下文 call|apply this -> 绑定的第一个参数
- arguments
是一个类似与数组的结构,用来接收函数调用时传入的实参
function f1() {
console.log(this);
}
f1();
var obj = {
name:"张三",
showName:function () {
console.log(this.name);
}
}
var name = "测试";
obj.showName(); //张三
var func = obj.showName;
func(); //张三 window.name
function test() {
console.log(this);
}
//01 普通调用
test(); //this -- window
//02 对象的方法来调用
obj.test = test;
obj.test(); //this -- obj
//03 构造函数方式调用
new test(); //this -- 内部新创建的对象
var o = {
des:"des_o"
};
window.test.call(o);
- 传入N个数字,返回最大值
function foo() {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if(max < arguments[i])
{
max = arguments[i];
}
}
//console.log(Array.isArray(arguments));;
return max;
}
console.log(foo(111, 2, 2, 3, 4, 5, 7, 78, 9, 10,99));
console.log(foo.length);
Function 小应用
- indexOf:获取指定元素在数组中对应的索引,如果不存在该元素那么就返回 -1
去重复数字
function demo() {
var arr = [];
//数组去重
for (var i = 0; i < arguments.length; i++) {
//每循环一次就判断当前的数据在arr中是否存在,如果不存在那么就push
if(arr.indexOf(arguments[i]) == -1)
{
arr.push(arguments[i]);
}
}
return arr;
}
console.log(demo(1, 2, 3, 4, 3, 2, 1, 2, 3, 5, 6, 9));
callee 和 caller
- callee:
指向的是函数自己
常用于递归调用中
递归:自己调用自己,要有结束退出条件 - caller:
指向的是函数的调用者
注意点:window 来调用函数的时候,指向的是 null 而不是 window
function f1() {
console.log(f1.caller); //打印函数的调用者
}
function f2() {
f1();
}
// f2();
f1();
返回累加之和
console.log((function (n) {
if (n == 1) {
return 1;
}
return arguments.callee(n - 1) + n;
})(34));
私有变量和函数
- 私有变量和函数(私有成员)
在构造函数内部声明的变量或者是函数 - 特权方法:
对象的方法 + 可以访问私有的变量
function Person() {
this.name = "默认的名称";
this.age = 23;
this.showName = function () {
console.log(this.name);
}
var des = "默认的属性";
var showDes = function () {
console.log(des);
}
this.show = function (str) {
console.log(this.name + this.age + des);
des = str;
console.log(des);
}
}
var p1 = new Person();
console.log(p1.name);
console.log(p1.des);
p1.showName();
// p1.showDes();
p1.show("乌拉乌拉");
// console.log(des);
// showDes();