前端面试之原生js,ajax,jquery,跨域,闭包,面向对象,原型,变量提升

专场:

1. 什么是ajax, 简述一下 ajax 请求数据的过程

AJAX即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。

通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

Ajax的使用

(1)创建`XMLHttpRequest`对象,也就是创建一个异步调用对象.

(2)创建一个新的`HTTP`请求,并指定该`HTTP`请求的方法、`URL`及验证信息.

(3)设置响应`HTTP`请求状态变化的函数.

(4)发送`HTTP`请求.

(5)获取异步调用返回的数据.

(6)使用JavaScript和DOM实现局部刷新.

getData(url, fn) {

    // 实例化XMLHttpRequest对象

    var xhr = new XMLHttpRequest();

    // 监听状态

    xhr.onreadystatechange = () => {

    // 数据请求完毕            判断状态码

    if (xhr.readyState === 4&&xhr.status === 200) {

    // 将数据转化成json在、数组

    fn && fn(JSON.parse(xhr.responseText))

    }

    }

    // 打开数据请求  请求方式,路径,同步false 异步true(默认)

    xhr.open('get/post', "路径", "true/false");

    // 发送数据

    xhr.send(null)

}

2. 简述 this 的 四种指向 问题

this指向的形式4种

a.如果是一般函数,this指向全局对象window;

b.在严格模式下"use strict",为undefined.

c.对象的方法里调用,this指向调用该方法的对象.

(call,apply,bind会改变this的指向)

.call(),  call(thisScope, arg1, arg2, arg3...)

.apply(), apply(thisScope, [arg1, arg2, arg3...]);两个参数

Bind(this) 返回的是一个函数

d.构造函数里的this,指向创建出来的实例.

3. jquery 的优点和缺点

JQ的优点:

(1)使用模块化思想,模块间保持独立,不会导致多个开发人员合作时产生冲突

(2)结构清晰,高内聚,低耦合

(3)多态的方式使方法可以重载,提高了代码的复用率

(4)jQuery 的链式调用以及回溯(dom操作的链式操作)

(5)jQuery.fn.extend 与 jQuery.extend方法来实现扩展静态方法或实例方法

JQuery的特点()

(1).一款轻量级的js框架。 JQuery核心js文件才几十kb,不会影响页面加载速度

(2).丰富的DOM选择器(CSS1-3 + XPath) JQuery的选择器用起来很方便,好比要找到某个dom对象的相邻元素js可能要写好几行代码,而JQuery一行代码就搞定了。

(3).链式表达式。 JQuery的链式操作可以把多个操作写在一行代码里,更加简洁。

(4).事件、样式、动画支持。 JQuery还简化了js操作css的代码,并且代码的可读性也比js要强。

(5).Ajax操作支持。JQuery简化了AJAX操作,后台只需返回一个JSON格式的字符串就能完成与前台的通信。

(6).跨浏览器兼容。JQuery基本兼容了现在主流的浏览器,不用再为浏览器的兼容问题而伤透脑筋。

(7).插件扩展开发。JQuery有着丰富的第三方的插件,例如:树形菜单、日期控件、图片切换插件、弹出窗口等等基本前台页面上的组件都有对应插件。

(8).可扩展性强。  JQuery提供了扩展接口:JQuery.extend(object),可以在JQuery的命名空间上增加新函数。JQuery的所有插件都是基于这个扩展接口开发的。

JQuery的缺点

<1>.不能向后兼容。每一个新版本不能兼容早期的版本。举例来说,有些新版本不再支持某些selector,新版jQuery却没有保留对它们的支持,而只是简单的将其移除。这可能会影响到开发者已经编写好的代码或插件。

<2>.插件兼容性。与上一点类似,当新版jQuery推出后,如果开发者想升级的话,要看插件作者是否支持。通常情况下,在最新版jQuery版本下,现有插件可能无法正常使用。开发者使用的插件越多,这种情况发生的几率也越高。我有一次为了升级到jQuery 1.3,不得不自己动手修改了一个第三方插件。

<3>.多个插件冲突。 在同一页面上使用多个插件时,很容易碰到冲突现象,尤其是这些插件依赖相同事件或selector时最为明显。这虽然不是jQuery自身的问题,但却又确实是一个难于调试和解决的问题。

<4>.jQuery的稳定性。 jQuery没有让浏览器崩溃,这里指的是其版本发布策略。jQuery 1.3版发布后仅过数天,就发布了一个漏洞修正版1.3.1。他们还移除了对某些功能的支持,可能会影响许多代码的正常运行。我希望类似修改不要再出现。

<5>.对动画和特效的支持差。 在大型框架中,jQuery核心代码库对动画和特效的支持相对较差。但是实际上这不是一个问题。目前在这方面有一个单独的jQuery UI项目和众多插件来弥补此点。

4. 跨域如何产生 如何解决跨域

跨域问题的产生就是浏览器的同源策略 只有当协议、端口、和域名都相同的页面,则两个页面 具有相同的源。只要有一个不同,就产生跨域问题

1 使用代理.代理就是用在后端监听这个端口,只要是这个端口,就转发到真正的服务器地址,获取数据后在通过同源的端口返回数据

2.使用jsonp script标签的src没有同源限制 jsonp通过script标签src获取接口 拼接了一个 callback,回调函数名称是 cb

3.使用CORS Cross-Origin Resource Sharing(CORS)跨域资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙 盒脚本的方法,以避开浏览器的同源策略,确保安全的跨域数据传输。 服务器一般需要增加如下响应头的一种或几种:

Access-Control-Allow-Origin: *

Access-Control-Allow-Methods: POST, GET, OPTIONS

Access-Control-Allow-Headers: X-PINGOTHER, Content-Type

Access-Control-Max-Age: 86400

跨域请求默认不会携带Cookie信息,如果需要携带,请配置下述参数:

"Access-Control-Allow-Credentials": true

// Ajax设置

"withCredentials": true、

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域

解决:

1、jsonp跨域

2、nginx反向代理(中间件):

3、PHP端修改header

4、document.domain

5、window.name

6、postMessage

7. call/apply 里面的第一个参数

5. 什么是闭包 项目如何使用闭包 闭包有什么优缺点

解释:函数套函数。闭包两个需求:1.必须有两个函数,并且是嵌套关系,外面的函数必须返回里面的函数;2.在全局中必须接收返回 函数作为变量储存

缺点:闭包最大缺点就是会造成内存泄漏,存在堆中,不会被垃圾回收;

闭包产生的原因:

Js 最大的缺点就是没有类,尤其是es5,自身没有面向对象,变量和函数通常都是写在同一个空间中,变量重名—污染,函数名重名—污染

而闭包能够形成一个封闭的空间,可以避免污染,储存私有变量,存在函数里面 ,这个私有变量不会在函数运行完后被清理 ,可以像全局变量一样被使用,不会失效。

优点:

1.内容更封闭,保证命名不会冲突;

2.模块化开发—封闭的模块化环境

6. 谈谈你对面向对象的理解 面向对象的特点

类与对象

Array  类

var obj =new Array()  变为对象

类:是一个抽象的概念

对象:实际的内容

类就是对某些个体的所有的方法和属性的集合

实例化过程:

1.先构造概念

2.将概念实例化就形成了对象

面向对象:先构造概念,然后将概念实例化,所有实例化对象都可以使用概念内的方法

通俗的理解就是:万物皆对象!世界上的任何事和物都可以被视为对象,而我们需要关注的是对象本身可以实现的功能,不需要深入理解构成对象的元素。

js中的面向对象

面向对象在js里有两个层次的含义,第一种是会使用面向对象函数;第二种是构造面向对象函数。

js也是面向对象中的一种写法,不过相对于java,js是一种弱数据类型,并不是严格意义上的面向对象。但是jq就是使用面向对象的写法创作出来的js库。

面向对象的特点

(“抽风机”谐音记忆)

面向对象有四个特点:

1. 抽象:抓住核心问题

2. 封装:即把能够实现功能的函数写成封装起来,在面向对象里叫做方法。简单来说就是把实现功能的函数写成方法。

3. 继承:继承的意思是,在实现同一种功能的前提下,新对象可以使用就对象的属性和方法。

4. 多态:一个变量在引用不同类型的情况下的不同状态。多态开发在开发组件和模块化开发的时候能节省很多资源。

原型(prototype)

原型可以用来构造函数的属性和方法,使这个构造函数的属性和方法成为公用的。使用原型的优点:在内存中节省资源,提高系统性能。

这是一个用原型构造的数组方法,将求和的sum方法挂在原型上,可以使这个方法被重复使用,当然,重点是节省内存资源。

使用原型还有一个优点,就是优先级:

原型的优先级类似于CSS中的优先级,没有使用原型的构造函数,就好比CSS中的行内样式,优先级高,而与原型挂钩的属性和方法 ,就像是style的内联样式,优先级低于行内样式。所以在调用同一种方法名的时候,系统会优先调用挂在原型上的方法!

7. 如何深入理解原型链

进行方法调用的时候,会先在自身上查找,如果没有就去该实例的原型链上查找,直到找到为止,如果没找到就返回undefined。

原型链就是创建一个构造函数,它会默认生成一个prototype属性并指向原型对象。使用下一个构造函数的原型对象作为这个构造函数的实例。即 nextFuction.prototype = new thisFuction();

在下下一个构造函数的原型对象 = new nextFuction。这样下去就会构成一条实例与原型之间的链条,这就是原型链。

在构造函数中定义的属性和方法实际上是实例的属性和方法。即只能出现在实例中。同理因为在构造函数SubType中定义的subProperty属性是实例属性,所以存在于instance中。实例中会有一个[[prototype]]内部属性指向构造函数的原型对象。这样就形成了一条链。

在通过原型链实现继承的情况下,当读取模式访问实例中的属性时,会先搜索实例,然后再搜索实例的原型,在一层一层直到找到或者到达原型链的末端停止,返回undefined。

其实我们上面的是少一环的,即Object。因为所有引用类型都是从object继承来的。

原型链就是设置构造函数的属性时,会向它的父元素上面的原型上查找,如果原型没有的话就去object上面查找,如果大写的Object上面没有的话,就为undefined,自己有的就用自己的

8. setInterval/setTimeout 传参数 的四种不同写法 setInterval(()=>,1)

一、采用字符串形式setInterval("foo(id)",1000);

二、匿名函数包装 window.setInterval(function() { foo (id); }, 1000);

三、定义返回无参函数的函数

function foo(id){

    alert(id);

}

function _foo(id){

    return function() {

    foo(id);

} }

window.setInterval(_foo(id),1000);

四、修改setInterval

var _sto = setInterval;

window.setInterval = function(callback,timeout,param){

    var args = Array.prototype.slice.call(arguments,2);

    var _cb = function() {

    callback.apply(null,args);

    }

    _sto(_cb,timeout);

}

window.setInterval(hello,3000,userName);

9. 如何区分 宿主对象 内置对象 本地对象 分别有哪些?

宿主对象  window  document    简单的说就是官方未定义的都是宿主对象

内置对象  不可以实例化的对象  例如: Global  Math

本地对象  可以实例化的对象 例如:  Object Array  Function Number RegExp Date ...

10. url https://www.aliyun.com/node/day?id=1234&price=100#level1

协议 域名 search query path pathname host hostname hash

假设这是一个url地址http://localhost:8080/a/b/c?a=1&b=2#abc,里面包含的部分:

url.parse(urlString[, parseQueryString[, slashesDenoteHost]])

将一个URL解析成一个对象,第2、3个参数都是boolean类型,parseQueryString定义是否将查询字符串query转化为object,默认为false不转换

用到的最多的就是pathname和query两个属性了,请注意区分host/hostname、search/query、path/pathname之间的区别

protocol: 'http:',//协议

host: 'localhost:8080',

port: '8080',//端口

hostname: 'localhost',域名

hash: '#abc',

search: '?a=1&b=2',

query: 'a=1&b=2',

pathname: '/a/b/c',

path: '/a/b/c?a=1&b=2',

href: 'http://localhost:8080/a/b/c?a=1&b=2#abc'

11. Query 中,$.data() 和 $(“#aa”).data() 各自是什么作用,有什么区别? 静态属性方 法 实例(prototype 原型对象)属性的方法

$.data()是从 Jquery对象 中取值,静态属性方法

$(“#aa”).data() 在页面元素里找到id为aa对象,从中获取data值,实例属性的方法

$.data()是静态属性的方法 通过data()函数存取的数据都是临时数据,一旦页面刷新,之前存放的数据都将被移除。

$(“#aa”).data()是实例(proto原型对象)属性的方法

向被选元素附加数据,或者从被选元素获取数据。

12. jQuery 中 , $.fn ($ = jQuery) 和 $.prototype 三种的区别 $ 和 jQuery 的区别

$是jquery的另一种表现形式;

$.fn是$.prototype的别名;

$.fn是$的原型对象

$拓展的方法是静态方法,可以使用$直接调用

$.fn拓展的方法是实例方法,必须由“对象”$("")来调用

function jQuery(){

this...

return jQuery = $

}

静态属性

jQuery.ajax = func ($.ajax)

jQuery.get = func

jQuer.post = $.psot = func

$.each = func

原型对象属性 (实例属性) $("#box").show ==> jQuery 的实例化 寻找DOM

jQuery.prototype.show = func

jQuery.prototype.hide = func

jQuery.prototype.css = func

$.fn = jQuery.fn = $.prototype

jQuery.js

jQuery 变量名

$ == jQuery fn = prototype

$.fn = jQuery.fn = $.prototype = jQuery.prototype = 原型对象

jQuery静态属性的扩展 $.getData

$.extend({

getData(){

}

})

jQuery原型对象属性扩展 $("#box").anmiateFade()

$.fn.extend({

anmiateFade(){

}

})

13. 简述一下 你对 TCP三次握手 的理解

"传输层"的功能,就是建立"端口到端口"的通信。相比之下,"网络层"的功能是建立"主机到主机"的通信。只要确定主机和端口,我们就能实现程序之间的交流。因此,Unix系统就把主机+端口,叫做"套接字"(socket)。有了它,就可以进行网络应用程序开发了。

现在,我们必须在数据包中加入端口信息,这就需要新的协议。最简单的实现叫做UDP协议,它的格式几乎就是在数据前面,加上端口号。UDP数据包,也是由"标头"和"数据"两部分组成。"标头"部分主要定义了发出端口和接收端口,"数据"部分就是具体的内容。然后,把整个UDP数据包放入IP数据包的"数据"部分,而前面说过,IP数据包又是放在以太网数据包之中的,所以整个以太网数据包现在变成了下面这样:UDP数据包非常简单,"标头"部分一共只有8个字节,总长度不超过65,535字节,正好放进一个IP数据包。

5.3 TCP协议

UDP协议的优点是比较简单,容易实现,但是缺点是可靠性较差,一旦数据包发出,无法知道对方是否收到。

为了解决这个问题,提高网络可靠性,TCP协议就诞生了。这个协议非常复杂,但可以近似认为,它就是有确认机制的UDP协议,每发出一个数据包都要求确认。如果有一个数据包遗失,就收不到确认,发出方就知道有必要重发这个数据包了。

因此,TCP协议能够确保数据不会遗失。它的缺点是过程复杂、实现困难、消耗较多的资源。

TCP数据包和UDP数据包一样,都是内嵌在IP数据包的"数据"部分。TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包不必再分割。

  上图画出了TCP建立连接的过程。假定主机A运行的是TCP客户程序,B运行的是TCP服务器程序。最初两端的TCP进程都处于CLOSED状态。图中在主机下面的是TCP进程所处的状态。A是主动打开连接,B是被动打开连接。

  B的TCP服务器进程先创建传输控制模块TCB,准备接受客户进程的连接请求,然后服务器进程就处于LISTEN(监听)状态,等待客户的连接请求

  首先A的TCP客户进程向B发出连接请求报文段,这时首部中的同步位SYN=1,同时选择一个初始序号seq=x。TCP规定,SYN报文段(即SYN=1的报文段)不能携带数据,但要消耗掉一个序号。这时,A的客户进程就进入SYN-SENT(同步已发送)状态。

  B收到连接请求报文段后,向A发送确认。在确认报文段中把SYN和ACK位都置为1,确认号是ack=x+1,同时也为自己选择一个初始序号seq=y。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。这时B的TCP服务器进程就进入SYN-RCVD(同步已收到)状态。

  A的TCP客户进程收到B的确认后,还要向B给出确认。确认报文段的ACK置为1,确认号ack=y+1,而自己的序号seq=x+1。这时,TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态,

  当B收到A的确认后,也会进入ESTABLISHED状态。

  以上给出的连接建立过程就是常说的TCP三次握手。

  为什么A还要发送一次确认呢?这主要是为了防止已失效的连接请求报文段突然又传送到了B,因而产生错误。

  假定A发出的某一个连接请求报文段在传输的过程中并没有丢失,而是在某个网络节点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误以为A又发了一次新的连接请求,于是向A发出确认报文段,同意建立连接。假如不采用三次握手,那么只要B发出确认,新的连接就建立了。

  由于A并未发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据。但B却以为新的运输连接已经建立了,并一直等待A发来数据,因此白白浪费了许多资源。

  采用TCP三次握手的方法可以防止上述现象发生。例如在刚才的情况下,由于A不会向B的确认发出确认,B由于收不到确认,就知道A并没有要求建立连接。

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接.

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入等待确认状态,等待服务器确认;

第二次握手:服务器接收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手.

14. 如何判断你当前手机浏览器的类型 userAgent (QQ , 微信 ,微博 ,华为)

(1)通过navigator.userAgent获取浏览器的userAgent字符串

(2)然后indexOf去查找各个浏览器名称/浏览器内核的名称,如果返回值不为-1,则该浏览器名称/内核即为你当前手机的手机浏览器/浏览器内核的类型

以pc端为例:

  var userAgent = navigator.userAgent

    if (userAgent.indexOf("Opera")> -1) {

        return "Opera"

    };

    //判断是否Firefox浏览器

    if (userAgent.indexOf("Firefox") > -1) {

        return "FF";

    }

    //判断是否chorme浏览器

    if (userAgent.indexOf("Chrome") > -1){

  return "Chrome";

    }

    //判断是否Safari浏览器

    if (userAgent.indexOf("Safari") > -1) {

        return "Safari";

    }

var browser = {

  versions: function() {

    var u = navigator.userAgent;

    return {

            trident: u.indexOf('Trident') > -1, //IE内核

            presto: u.indexOf('Presto') > -1, //opera内核

            webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核

            gecko: u.indexOf('Firefox') > -1, //火狐内核Gecko

            mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端

            ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios

            android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android

            iPhone: u.indexOf('iPhone') > -1 , //iPhone

            iPad: u.indexOf('iPad') > -1, //iPad

            webApp: u.indexOf('Safari') > -1 //Safari

        };

    }()

}

15. $.fn.extends $.extends 两者的区别

jQuery.fn = jQuery.prototype;

jQuery为开发插件提拱了两个方法,分别是:

jQuery.fn.extend(object):  给jQuery实例对象添加方法,例如$("#aaa").click()这个jq实例对象所能运用的click()方法

jQuery.extend(object):    为扩展jQuery类本身.为类添加新的方法(添加静态方法),例如$.ajax()这个jq自带方法

16. 说一下什么是变量提升 如何解决变量提升

当我们在一个变量定义前调用这个变量会输出一个undefind,因为我们用var来声明这个变量的时候会在调用这个变量的前面假设定义了一个没有被赋值的变量 ,这就是变量提升,当我们用function关键字来定义一个函数的时候在任何地方我们都可以调用这个函数,如果我们用变量声明的方式来定义函数,在函数定义的前面调用函数会报undefind,也是因为变量提升, 用let声明一个变量就不会存在变量提升

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335