一. typeof操作符

typeof操作符用于返回正在使用值的类型。

// 使用原始值
let mNull = null;
let mUndefined = undefined;
let mString = 'mazey';
let mNumber = 123;
let mBoolean = true;
let mFunction = function () {
return true;
}; // 用构造函数的方式new一个实例
let oString = new String('cherrie');
let oRegExp = new RegExp('^[0-9]+$');
let oFunction = new Function('x', 'y', 'return x + y'); let oObj = {};
let oNew = new Object(); // typeof值
console.log(typeof mNull); // object
console.log(typeof mUndefined); // undefined
console.log(typeof mString); // string
console.log(typeof mNumber); // number
console.log(typeof mBoolean); // boolean
console.log(typeof mFunction); // function
console.log(typeof oString); // object
console.log(typeof oRegExp); // object
console.log(typeof oFunction); // function
console.log(typeof oObj); // object
console.log(typeof oNew); // object

在《JavaScript启示录》中new RegExp()介绍会返回function,但是事实上我在chrome控制台中看到的是object

于是我console.log(new RegExp('^[0-9]+$')),打印出来的是字符串/^[0-9]+$/

console.log(new RegExp('^[0-9]+$')); // /^[0-9]+$/
console.log(RegExp); // ƒ RegExp() { [native code] } 原始值
console.log(String); // ƒ String() { [native code] } 原始值
console.log(/^[0-9]+$/); // /^[0-9]+$/
console.log(new RegExp('^[0-9]+$') === /^[0-9]+$/); // false
console.log(RegExp('^[0-9]+$') === /^[0-9]+$/); // false

综上可以看出现版本RegExpString Number一样属于JavaScript的原始值。

Math作为JavaScript中的静态对象回返回什么呢?

console.log(typeof Math); // object
console.log(typeof Math.PI); // number
console.log(typeof Math.ceil); // function

所以Math__proto__还是Objecttypeof还能返回对象的属性和方法的类型。

typeof使用场景

1.判断某个变量是否已定义

console.log(typeof aaa); // 'undefined'

// 判断
if (typeof bbb === 'undefined') {
console.log('变量未定义');
}

2.区分原始值和复杂值(对象值)

因为复杂值往往返回object,当然有个例外就是原始值里面的null也返回object,然后function作为Object的实例也是复杂值。

// 判断是否时复杂值(对象值)
function isObject (m) {
return (typeof m === 'function' || (typeof m === 'object' && m !== null));
} console.log(isObject(new RegExp('123'))); // true
console.log(isObject('123')); // false
console.log(isObject(String('123'))); // false
console.log(isObject(null)); // false // 判断是否是原始值
function isNative (m) {
return (m === null || (typeof m !== 'object' && typeof m !== 'function'));
} console.log(isNative(new RegExp('123'))); // false
console.log(isNative('123')); // true
console.log(isNative(String('123'))); // true
console.log(isNative(null)); // true

3.检测某个变量是否是函数

当使用闭包时判断是函数后再进行下一步。

function qqq () {
let a = 0;
let b = function () {
a++;
console.log(a);
};
return b;
} let ccc = qqq();
console.log(typeof ccc); // function
if (typeof ccc === 'function') {
ccc(); // 1
ccc(); // 2
ccc(); // 3
ccc(); // 4
}

二. instanceof操作符

通过使用instanceof操作符,可以确定一个对象是否是特定构造函数实例,返回truefalse

instanceof只适用于构造函数创建返回的复杂对象实例

任何时间判断一个对象(复杂值)是否是Object的实例时,它都将返回true,因为所有对象都继承自Object()构造函数。

let oFather = function () {
this.firstName = 'mazey';
};
oFather.prototype.lastName = 'qian'; // 实例
let oSon = new oFather();
console.log(oSon instanceof oFather); // true // 继承
let nFather = function () {};
nFather.prototype = new oFather();
nFather.construction = nFather;
console.log(nFather.firstName); // undefined
console.log(nFather.prototype.lastName); // qian
console.log(nFather instanceof oFather); // false
console.log(new nFather() instanceof nFather); // true // 相对于Object来说
console.log('123' instanceof Object); // false
console.log(new String('123') instanceof Object); // true 构造出来的实例
console.log(null instanceof Object); // false

instanceof使用场景

判断在一个继承关系中实例是否属于它的父类。

// 继承
let oFather = function () {};
let nFather = function () {};
nFather.prototype = new oFather();
nFather.construction = nFather; let nSon = new nFather();
console.log(nSon instanceof nFather); // true
console.log(nSon instanceof oFather); // true

三. in操作符和hasOwnProperty方法

in操作符可以检查一个对象的属性,包括来自原型链的属性,hasOwnProperty()方法可以检查来自非原型链属性的对象。

例如现在有一个对象let obj = {name: 'mazey'};name是它自身定义的属性,toString是它从原型链上继承下来的属性。

let obj = {name: 'mazey'};
console.log('name' in obj); // true
console.log('toString' in obj); // true
console.log('name' in Object); // true
console.log(obj.hasOwnProperty('name')); // true
console.log(obj.hasOwnProperty('toString')); // false
console.log(Object.hasOwnProperty('name')); // true

所以in操作符查找的范围更广一点,可以用hasOwnProperty()判断是否是对象自身的属性,而不是通过类似obj.prototype.foo = 'foo';这样定义的。

hasOwnProperty方法使用场景

在实际项目中经常使用for...in...来遍历对象中可枚举的属性,但是for...in...常常把原型obj.prototype.xxx中的属性也列举出来,所以在循环的时候可以加上hasOwnProperty()方法判断下。

function obj0 () {
this.name = 'mazey',
this.age = '24'
};
obj0.prototype.gender = 'male';
let obj1 = new obj0(); // 打印所有可枚举属性
for (let key in obj1) {
console.log(key); // name age gender 从原型链上继承下来的属性也会被打印出来
} // 过滤掉原型链上的属性
for (let key in obj1) {
if (obj1.hasOwnProperty(key)) {
console.log(key); // name age
}
}

四. 总结

1.typeof可以判断使用值的类型,注意null返回object。 2.instanceof验证构造函数构造出来的实例,可以用来判断一个对象是否属于一个父类。 3.hasOwnProperty方法常常与in操作符搭配使用,用来遍历一个对象自身的属性。

五. 相关扩展

1.删除对象的属性

若想把一个对象的自身属性完全删除,要使用delete操作符。

let obj0 = {
name: 'mazey',
age: 24
}; // 删除age属性
delete obj0.age;
console.log(obj0.hasOwnProperty('age')); // false
console.log('age' in obj0); // false // 试着删除原型链上的属性 toString
delete obj0.toString
console.log('toString' in obj0); // true

需要注意的是delete不会删除原型链上的属性。

2.可枚举

每个对象的属性都分为可枚举和不可枚举属性,可以使用propertyIsEnumerable()方法来检查哪些属性是可枚举的。

每个对象都有一个propertyIsEnumerable方法。此方法可以确定对象中指定的属性是否可以被for...in(for...in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行)循环枚举,但是通过原型链继承的属性除外。如果对象没有指定的属性,则此方法返回false

有的资料说只要能被for..in遍历的属性就是可枚举的,实际上要排除从原型链上继承下来的属性,只有自身的属性是可枚举的。

// 第一个构造函数
function ConFun0 () {
this.firstName = 'mazey';
}
ConFun0.prototype.firstCom = 'bang'; // 第二个构造函数
function ConFun1 () {
this.secondName = 'qian';
}
// 继承第一个
ConFun1.prototype = new ConFun0();
ConFun1.prototype.constructor = ConFun1; // 实例
let obj = new ConFun1();
obj.girlName = 'cherrie'; // 是否可枚举
console.log(obj.propertyIsEnumerable('constructor')); // false
console.log(obj.propertyIsEnumerable('firstName')); // false
console.log(obj.propertyIsEnumerable('firstCom')); // false
// 通过原型链继承的属性不是可枚举
console.log(obj.propertyIsEnumerable('secondName')); // true
console.log(obj.propertyIsEnumerable('girlName')); // true for (let key in obj) {
console.log(key); // secondName girlName (原型链上的属性也会被打印出来->) firstName constructor firstCom
} console.log(`---分割线---`); for (let key in obj) {
// 过滤掉原型链上的属性
if (obj.hasOwnProperty(key)) {
console.log(key); // secondName girlName
}
}

所以可枚举的属性一定能被for..in循环遍历出来,但是for...in循环遍历出来的属性不一定是可枚举的,需排除从原型链上继承下来的属性,这里可以通过hasOwnProperty()方法过滤掉不可枚举属性。

JavaScript中typeof,instanceof,hasOwnProperty,in的用法和区别

JavaScript中typeof,instanceof,hasOwnProperty,in的用法和区别的更多相关文章

  1. Javascript中typeof instanceof constructor的区别

    typeof typeof,是一个运算符,运算中需要一个操作数,运算的结果就是这个操作数的类型,运算的结果是一个字符串.他有一定的局限性,对于对象类型的值,只能得到一个object结果,却不能精确得到 ...

  2. 【JavaScript中typeof、toString、instanceof、constructor与in】

    JavaScript中typeof.toString.instanceof.constructor与in JavaScript 是一种弱类型或者说动态语言.这意味着你不用提前声明变量的类型,在程序运行 ...

  3. javascript中typeof和instanceof用法的总结

    今天在看相应的javascript书籍时,遇到了typeof和instanceof的问题,一直不太懂,特地查资料总结如下: JavaScript 中 typeof 和 instanceof 常用来判断 ...

  4. javascript中typeof与instanceof的区别

    JavaScript 中 typeof 和 instanceof 常用来判断一个变量是否为空,或者是什么类型的.但它们之间还是有区别的: typeof typeof 是一个一元运算,放在一个运算数之前 ...

  5. javascript 中 typeof 的使用

    javascript 中 typeof 的使用 javascript有五种基本的数据类型(简单数据类型),它们分别是:String.Undefined.Null.Boolean和Number.还有一种 ...

  6. JavaScript 中定义变量时有无var声明的区别

    关于JavaScript中定义变量时有无var声明的区别 var a=5; //正确 a=5; //正确 在javascript中,以上两种方法都是定义变量的正确方法.微软的Script56.CHM中 ...

  7. JavaScript中querySelector()和getElementById()(getXXXByXX)的区别

    在日常开发中,使用JavaScript获取元素的时候,最常用的方法就是document.getElementById(getXXXByXX)方法.但是最近发现有很多地方使用的是querySelecto ...

  8. 脚本引用中的defer和async的用法和区别

    之前的博客漫谈前端优化中的引用资源优化曾经提到过脚本引用异步设置defer.async,没有细说,这里展开一下,谈谈它们的作用和区别,先上张图来个针对没用过的小伙伴有个初始印象: 是的,就是在页面脚本 ...

  9. 浅谈JS中的!=、== 、!==、===的用法和区别 JS中Null与Undefined的区别 读取XML文件 获取路径的方式 C#中Cookie,Session,Application的用法与区别? c#反射 抽象工厂

    浅谈JS中的!=.== .!==.===的用法和区别   var num = 1;     var str = '1';     var test = 1;     test == num  //tr ...

随机推荐

  1. python Logging的使用

    日志是用来记录程序在运行过程中发生的状况,在程序开发过程中添加日志模块能够帮助我们了解程序运行过程中发生了哪些事件,这些事件也有轻重之分. 根据事件的轻重可分为以下几个级别: DEBUG: 详细信息, ...

  2. 启动tomcat爆错 the JRE could not be found

    启动报错,如下图: 之前更改了了一个较低的jdk的版本看了看一个项目的代码,不知所云,然后再改回来, 混乱之中只要启动Tomcat就出现这种错误,还是无法找到JRE,最后如此解决: 在Windows- ...

  3. PHP操作Memcached

    一.PHP连接Memcached: 一个简单的使用示例: $memcache = new Memcache; $memcache->connect("127.0.0.1",1 ...

  4. java 随记

    后台开发的过程中积累的关于java的杂记 架构 SSH框架 为什么要分层? 因为分层使代码变得清晰,容易写也容易阅读,更重要的是让代码扩展性更好,层与层之间的改动不会互相影响 各层的分工 dao--与 ...

  5. 使用Git 本地代码提交到 GitHub

    第一步:下载Git 工具 在官网下载 https://git-scm.com/ 第二部:注册官方账号 创建一个村代码的仓库 注册地址https://github.com/ 第三部:本地代码 通过Git ...

  6. C#设计模式--简单工厂模式

    简单工厂模式是属于创建型模式,但不属于23种GOF设计模式之一. 举一个例子:一个公司有不同的部门,客户根据需要打电话到不同的部门.客户相当于上端,不同部门相当于下端.不使用简单工厂模式来实现的例子如 ...

  7. 用js判断是否为手机浏览,如果是手机浏览就跳转到手机站

    <script type="text/javascript"> function browserRedirect() { var sUserAgent= navigat ...

  8. Android 开发笔记___滚动视图__scroll view

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  9. React Native填坑之旅 -- 使用react-navigation代替Navigator

    Navigator已经被React Native废弃了.也许你可以在另外的一个依赖库里react-native-deprecated-custom-components里找到.不过既然官方推荐的是re ...

  10. Netty——高级发送和接收数据handler处理器

    netty发送和接收数据handler处理器 主要是继承 SimpleChannelInboundHandler 和 ChannelInboundHandlerAdapter 一般用netty来发送和 ...