0408JS面经

21.for in、Object. keys 和 Object. getOwnPropertyNames 对属性遍历有什么区别

  • for in 会遍历自身及原型链上的可枚举属性
  • Object. keys 会将对象自身的可枚举属性的 key 输出
  • Object. getOwnPropertyNames会将自身所有的属性的 key 输出
    解析:
    ECMAScript 将对象的属性分为两种:数据属性和访问器属性。
var parent = Object.create(Object.prototype, {
    a: {
        value: 123,
        writable: true,
        enumerable: true,
        configurable: true
    }
});
// parent继承自Object.prototype,有一个可枚举的属性a(enumerable:true)。

var child = Object.create(parent, {
    b: {
        value: 2,
        writable: true,
        enumerable: true,
        configurable: true
    },
    c: {
        value: 3,
        writable: true,
        enumerable: false,
        configurable: true
    }
});
//child 继承自 parent ,b可枚举,c不可枚举

for in

for (var key in child) {
    console.log(key);
}
// b
// a
// for in 会遍历自身(b)及原型链上的可枚举属性(a),自身属性c不能枚举

Object.keys

console.log(Object.keys(child));
// ["b"]
// Object.keys 会将对象自身的可枚举属性的key输出

Object. getOwnPropertyNames

console.log(Object.getOwnPropertyNames(child));
// ["b","c"]
// 会将自身所有的属性的key输出

补充:
什么是可枚举属性?

可枚举属性是指那些内部 “可枚举” 标志设置为 true 的属性。对于通过直接的赋值和属性初始化的属性,该标识值默认为即为 true。但是对于通过 Object.defineProperty 等定义的属性,该标识值默认为 false。
其中js中基本包装类型的原型属性是不可枚举的,如Object, Array, Number等。
可枚举的属性可以通过for…in循环进行遍历(除非该属性名是一个Symbol),或者通过Object.keys()方法返回一个可枚举属性的数组

补充:
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
语法:Object.create(proto, [propertiesObject])

  • proto:新创建对象的原型对象。
  • propertiesObject:可选
    • 若没有指定为 undefined,则是要添加到新创建对象的可枚举属性
    • 即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。
    • 这些属性对应Object.defineProperties()的第二个参数
    • 返回值:一个新对象,带着指定的原型对象和属性。

22. iframe 跨域通信和不跨域通信

不跨域通信
主页面

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title></title>
</head>

<body>
    <iframe name="myIframe" id="iframe" class="" src="flexible.html" width="500px" height="500px">
    </iframe>
</body>
<script type="text/javascript" charset="utf-8">
    function fullscreen() {
        alert(1111);
    }
</script>

</html>

子页面

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title></title>
</head>

<body>
    我是子页面
</body>
<script type="text/javascript" charset="utf-8">
    // window.parent.fullScreens()
    function showalert() {
        alert(222);
    }
</script>

</html>

1、主页面要是想要调取子页面的 showalert 方法

myIframe.window.showalert();
  1. 子页面要调主页面的 fullscreen 方法
window.parent.fullScreens();
  1. js 在 iframe 子页面获取父页面元素:
window.parent.document.getElementById("元素id");
  1. js 在父页面获取 iframe 子页面元素代码如下:
window.frames["iframe_ID"].document.getElementById("元素id");

跨域通信
使用postMessage(官方用法)

子页面

window.parent.postMessage("hello", "http://127.0.0.1:8089");

父页面接收

window.addEventListener("message", function(event) {
    alert(123);
});

为什么会跨域??
为了保证用户信息的安全,95年的时候Netscape公司引进了同源策略,里面的同源指的是三个相同:协议、域名、端口
违反了同源策略就会出现跨域问题,主要表现为以下三方面:

  • 无法读取cookie、localStorage、indexDB
  • DOM无法获得
  • ajax请求无法发送

场景

最近在做一个需求,需要用iframe引入一个别人封装好的类似视频播放器的东西。iframe里面有一个全屏的按钮,点击后需要页面让iframe全屏,由于受到同源策略的限制,iframe无法告诉页面全屏。

解决办法

  1. 设置domain
    document.domain作用是获取/设置当前文档的原始域部分,同源策略会判断两个文档的原始域是否相同来判断是否跨域。这意味着只要把这个值设置成一样就可以解决跨域问题了。
    在此我将domain设置为一级域名的值,a页面url为a.demo.com,a页面中iframe引用的b页面url为b.demo.com,具体设置为
document.domain = 'demo.com'

设置完之后,在a页面的window上挂载使iframe全屏的方法

// a页面
window.toggleFullScreen = () => {
 // do something
}

在b页面上可以直接获取到a页面的window对象并直接调用

// b页面
window.parent.toggleFullScreen()

但是这个值的设置也有一定限制,只能设置为当前文档的上一级域或者是跟该文档的URL的domain一致的值。如url为a.demo.com,那domain就只能设置为demo.com或者a.demo.com。因此,设置domain的方法只能用于解决主域相同而子域不同的情况

  1. 使用中间页面
    可以使用一个与a页面同域名但不同路由的c页面作为中间页面,b页面加载c页面,c页面调用a页面的方法,从而实现b页面调用a页面的方法。具体操作如下:
    在a页面的node层新开一个路由,此路由加载一个c页面作为中间页面,c页面的url为a.demo.com/c。c页面只是一个简单的html页面,在window的onload事件上调用了a页面的方法。
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title></title>
</head>
<body>
 <script>
  window.onload = function () {
   parent.parent.toggleFullScreen();
  }
 </script>
</body>
</html>

由于c页面和a页面是符合同源策略的,所以可以避开跨域问题,执行全屏的方法

路由:抽象点说就是:为 http request 中的 path_uri 与执行脚本做绑定(映射)!所谓的执行脚本,就是一段处理业务逻辑的代码,执行脚本可以是 php,java,js 等!举个例子,在 MVC 结构中,route 的会将 uri 映射到 controller,具体业务逻辑在 controller 里面进行。

  1. window.postMessage() 方法
    window.postMessage方法可以安全地实现跨源通信,写明目标窗口的协议、主机地址或端口就可以发信息给它。
    https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
    可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当**执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) **时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
// b页面
parent.postMessage(
 value,
 "http://a.demo.com"
);
// a页面
window.addEventListener("message", function( event ) {
 if (event.origin !== 'http://b.demo.com') return;
 toggleFullScreen()
 });

为了安全,收到信息后要检测下event.origin判断是否要收信息的窗口发过来的。

23.H5与Native如何交互

Hybrid架构的核心就是JSBridge交互,而实现这个交互的前提是弄清楚H5和Native端的交互
什么是JSBridge?
主要是给 JavaScript 提供调用 Native 功能的接口,让混合开发中的前端部分可以方便地使用 Native 的功能(例如:地址位置、摄像头)。
而且 JSBridge 的功能不止调用 Native 功能这么简单宽泛。实际上,JSBridge 就像其名称中的Bridge的意义一样,是 Native 和非 Native 之间的桥梁,它的核心是构建 Native 和非 Native 间消息通信的通道,而且这个通信的通道是双向的。
在这里插入图片描述
https://blog.csdn.net/yuzhengfei7/article/details/93468914

本文主要介绍Native端(Android/iOS)和H5端(泛指前端)的交互原理
https://www.jianshu.com/p/477ea20b1ece?from=singlemessage

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值